CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-55830

CVE-2026-55830: Complete Sandbox Escape via Positional-Only Arguments in RestrictedPython

Amit Schendel
Amit Schendel
Senior Security Researcher

Aug 29, 2026·6 min read·23 visits

Executive Summary (TL;DR)

Incomplete validation of positional-only arguments in RestrictedPython allowed attackers to shadow security hooks and escape the sandbox.

A critical security flaw was identified in RestrictedPython prior to version 8.3 where positional-only arguments introduced in Python 3.8 were not properly validated. This allowed an attacker executing code within the sandbox to shadow critical security guards like `_write_` and `_getattr_`, leading to a complete sandbox escape and arbitrary code execution on the underlying server.

Vulnerability Overview

RestrictedPython is a specialized tool designed to define a safe subset of the Python language. It is commonly integrated into frameworks such as Zope and Plone to allow the execution of untrusted, user-supplied code in a restricted execution environment. To achieve this, RestrictedPython parses source code into an Abstract Syntax Tree (AST) and rewrites potentially hazardous operations into safe, validation-wrapped calls.

This rewritten AST relies on security guard hooks such as _getattr_, _getitem_, and _write_ to validate attribute access, subscripts, and mutation operations at runtime. These hooks are dynamically injected into the restricted program's global execution namespace. The security model relies entirely on preventing the sandboxed code from modifying or shadowing these protected identifiers, which are reserved and prefixed with leading underscores.

Prior to version 8.3, a structural omission existed in RestrictedPython's AST validation parser. When defining function parameter names, the validation engine failed to inspect positional-only arguments introduced in Python 3.8. This failure allows an attacker to bypass name-checking restrictions, leading to complete sandbox evasion and potential arbitrary code execution.

Root Cause Analysis

The root cause of this vulnerability lies in the Abstract Syntax Tree (AST) translation phase, specifically within the check_function_argument_names method inside src/RestrictedPython/transformer.py. This method is responsible for validating all parameter names in function and lambda definitions. Its purpose is to ensure that no parameter shadows the injected security hooks by starting with an underscore, such as _write_ or _getattr_.

In Python 3.8, PEP 570 introduced positional-only parameters, which are separated from other arguments by a forward slash (/). To support this syntax, the Python AST was updated to store these parameters in a distinct list field named posonlyargs under the function arguments node. However, the AST transformer in RestrictedPython was not updated to iterate through this newly introduced list.

Consequently, the validation loop inside check_function_argument_names checked standard arguments (args), keyword-only arguments (kwonlyargs), variable arguments (vararg), and keyword arguments (kwarg), but entirely omitted posonlyargs. This omission allowed positional-only arguments named after security hooks to pass compilation without throwing an error.

Code Analysis

A review of the vulnerable implementation in src/RestrictedPython/transformer.py highlights the missing check for the posonlyargs collection.

# Vulnerable implementation in RestrictedPython/transformer.py
def check_function_argument_names(self, node):
    # The posonlyargs collection is completely ignored here
    for arg in node.args.args:
        self.check_name(node, arg.arg)
 
    for arg in node.args.kwonlyargs:
        self.check_name(node, arg.arg)
 
    if node.args.vararg is not None:
        self.check_name(node, node.args.vararg.arg)
 
    if node.args.kwarg is not None:
        self.check_name(node, node.args.kwarg.arg)

The patch applied in commit 3737596ec9f28c34a073cc845bd2f4c0a80cb671 addresses this gap by prepending a loop that checks node.args.posonlyargs before verifying the remaining argument types.

# Patched implementation in RestrictedPython/transformer.py
def check_function_argument_names(self, node):
    # Added check to ensure positional-only parameters are validated
    for arg in node.args.posonlyargs:
        self.check_name(node, arg.arg)
 
    for arg in node.args.args:
        self.check_name(node, arg.arg)
 
    for arg in node.args.kwonlyargs:
        self.check_name(node, arg.arg)
 
    if node.args.vararg is not None:
        self.check_name(node, node.args.vararg.arg)
 
    if node.args.kwarg is not None:
        self.check_name(node, node.args.kwarg.arg)

This simple addition closes the validation gap. Any attempt to use restricted identifiers in positional-only parameters will trigger a compilation error, maintaining the integrity of the sandbox's execution environment.

Exploitation Methodology

Exploitation of CVE-2026-55830 requires the capability to compile and execute custom Python scripts within the restricted environment. Because the compiler fails to check positional-only arguments, an attacker can define a function or lambda where a positional-only argument is named exactly after a protected global guard, such as _write_.

# Shadowing the global write guard hook
def escape_sandbox(_write_=lambda obj: obj, /):
    # Inside this scope, attribute write operations use the local _write_
    pass

When Python compiles this function, it generates bytecode that resolves _write_ using the local scope rather than the global environment. At runtime, the local parameter _write_ is initialized with the attacker-controlled default lambda value. Any attribute write operation executed within the scope of this function is redirected through this lambda, which bypasses the validation and returns the raw target object.

An attacker can use this bypassed validation to access and modify the execution environment's internal namespace. By overriding the global dictionary's _getattr_ and _write_ hooks, the attacker disables the security boundary completely. This allows the script to import standard modules such as os or subprocess and execute arbitrary system commands on the host machine.

Impact Assessment

The security impact of CVE-2026-55830 is classified as High, with a CVSS v3.1 base score of 8.3. The vulnerability represents a complete breakdown of the isolation boundary provided by RestrictedPython, allowing sandboxed code to escape and achieve execution in the context of the parent application process.

An attacker who successfully escapes the sandbox can read and write arbitrary files, compromise system configurations, and access database credentials or environment variables stored on the host. If the parent application is running with elevated privileges, the entire hosting environment can be compromised.

While the vulnerability requires high privileges to submit and run scripts, the exploitation complexity is low because the bypass works reliably without relying on race conditions or system state. The scope change metric is set to 'Changed' because the impact extends from the restricted interpreter to the host operating system.

Remediation and Mitigation

The recommended remediation for this vulnerability is to upgrade RestrictedPython to version 8.3 or higher. If immediate upgrading is not possible, defensive mitigations must be implemented to inspect user-provided scripts prior to passing them to the RestrictedPython compiler.

Organizations can deploy an AST pre-filter utility that parses the incoming source code and rejects any structure containing positional-only arguments that begin with an underscore. This can be integrated into the application's intake validation pipelines.

import ast
 
def validate_ast_safety(source: str) -> bool:
    try:
        tree = ast.parse(source)
    except SyntaxError:
        return False
    for node in ast.walk(tree):
        if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef, ast.Lambda)):
            for arg in node.args.posonlyargs:
                if arg.arg.startswith('_'):
                    return False
    return True

Additionally, applications should employ strong process isolation. Running the python process within a containerized environment with minimal privileges and strict network access controls can limit the post-exploitation damage of a sandbox escape.

Technical Appendix

CVSS Score
8.3/ 10
CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:H/I:H/A:L
EPSS Probability
0.40%

Affected Systems

RestrictedPythonZopePlone
AttributeDetail
CWE IDCWE-184
Attack VectorNetwork
CVSS v3.18.3 (High)
EPSS Score0.00401 (Percentile: 33.04%)
Exploit StatusProof of Concept (PoC)
CISA KEV StatusNot Listed
ImpactArbitrary Code Execution (ACE) via Sandbox Escape
CWE-184
Incomplete List of Disallowed Inputs

Vulnerability Timeline

Official security patch committed to RestrictedPython main branch
2026-06-16
GitHub Security Advisory GHSA-ffg3-p8fm-mjx2 published
2026-07-08
CVE-2026-55830 published to NVD
2026-07-08
CVE record and CVSS score finalized
2026-07-09

More Reports

•2 minutes ago•CVE-2026-109619
9.2

CVE-2026-109619: Remote Code Execution in PHP Core via Stale Global State Memory Corruption (PHP2Shell)

CVE-2026-109619 (PHP2Shell) is a critical Use-After-Free vulnerability in the core PHP engine caused by improper global state cleanup during out-of-memory exception handling across persistent worker requests.

Alon Barad
Alon Barad
1 views•6 min read
•5 minutes ago•CVE-2026-113721
4.5

CVE-2026-113721: Unsafe Link Resolution in virtualenv File Generation

In Python virtualenv prior to version 21.14.9, activation script generators and configuration writers use Path.exists() before writing files. Because Path.exists() resolves symbolic links, it returns False for dangling symlinks. Consequently, virtualenv skips unlinking pre-planted symbolic links or hard links, writing data directly to target locations outside the intended virtual environment directory.

Amit Schendel
Amit Schendel
1 views•5 min read
•9 days ago•CVE-2026-87697
8.8

CVE-2026-87697: Untrusted Deserialization in .NET PresentationCore Clipboard Handling

A remote code execution vulnerability exists in Microsoft .NET due to untrusted data deserialization within the PresentationCore component. The flaw stems from implicit auto-conversion flags during clipboard data retrieval operations.

Alon Barad
Alon Barad
31 views•5 min read
•9 days ago•CVE-2026-70007
8.8

CVE-2026-70007: Out-of-Bounds Write Vulnerability in .NET Framework and WPF Subsystem

An out-of-bounds write vulnerability in Microsoft .NET Framework, .NET runtime, and Visual Studio allows unauthenticated remote attackers to execute arbitrary code via crafted pixel-shader bytecode or auto-converted clipboard payloads.

Amit Schendel
Amit Schendel
19 views•6 min read
•10 days ago•CVE-2026-70186
7.5

CVE-2026-70186: ASP.NET Core Denial of Service Vulnerability via Framework Deadlock

ASP.NET Core contains a thread deadlock vulnerability (CWE-833) that allows an unauthenticated remote attacker to cause a denial of service over the network by exhausting server thread pool resources.

Amit Schendel
Amit Schendel
18 views•5 min read
•10 days ago•CVE-2026-70035
8.8

CVE-2026-70035: Insecure Deserialization Remote Code Execution in Microsoft .NET Framework and .NET Runtime

CVE-2026-70035 is a high-severity Remote Code Execution (RCE) vulnerability in Microsoft .NET Framework, .NET runtime, and Visual Studio caused by improper handling during the deserialization of untrusted data (CWE-502). An unauthenticated attacker can execute arbitrary code within the context of the affected process by delivering a crafted serialized payload.

Amit Schendel
Amit Schendel
24 views•6 min read