Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-55830

CVE-2026-55830: RestrictedPython Auth Bypass Vulnerability

CVE-2026-55830 is an authentication bypass flaw in RestrictedPython that allows attackers to shadow protected guard hooks via positional-only arguments. This post covers technical details, affected versions, and patches.

Published:

CVE-2026-55830 Overview

CVE-2026-55830 is a sandbox escape vulnerability in RestrictedPython, a tool that defines a subset of the Python language for running untrusted code in trusted environments. The check_function_argument_names() function rejected protected guard hook names for regular, variadic, and keyword-only arguments but failed to validate positional-only arguments. Attackers with permission to submit RestrictedPython source can shadow protected names such as __getattr__, _getitem_, _write_, or _print_ using a positional-only parameter. This bypasses the embedding application's access policy. The issue affects all versions prior to 8.3 and maps to CWE-184: Incomplete List of Disallowed Inputs.

Critical Impact

A successful bypass allows untrusted code to escape the RestrictedPython sandbox and violate the host application's access policy, potentially leading to unauthorized attribute access, data disclosure, and modification of protected state.

Affected Products

  • RestrictedPython versions prior to 8.3
  • Applications embedding RestrictedPython (including Zope and Plone deployments)
  • Any service that executes user-supplied Python through RestrictedPython

Discovery Timeline

  • 2026-07-08 - CVE-2026-55830 published to the National Vulnerability Database (NVD)
  • 2026-07-08 - Last updated in NVD database

Technical Details for CVE-2026-55830

Vulnerability Analysis

RestrictedPython transforms Python source into a restricted abstract syntax tree (AST) before execution. During transformation, check_function_argument_names() in transformer.py walks function argument nodes and rejects reserved names that begin with an underscore. These reserved names correspond to security hooks the embedding application injects into the sandbox, including _getattr_, _getitem_, _write_, and _print_.

The check iterated over node.args.args, node.args.vararg, node.args.kwarg, and node.args.kwonlyargs, but omitted node.args.posonlyargs. Positional-only parameters, introduced in Python 3.8 via PEP 570, appear before the / separator in a function signature. A crafted function definition can declare a positional-only parameter named _getattr_, which then shadows the injected guard within the function's local scope.

With the guard shadowed, attribute and item access performed inside the function body no longer route through the policy-enforcing hook. The untrusted code then reaches Python objects and attributes the embedding application intended to restrict.

Root Cause

The root cause is an incomplete deny-list in the AST validator. The check_function_argument_names() method did not enumerate every AST field that can introduce a parameter name into the local scope, leaving positional-only arguments unchecked.

Attack Vector

Exploitation requires the ability to submit RestrictedPython source to the trusted environment, so the attacker must already hold privileges to author or edit executable content (for example, a TTW template author in Zope). The attacker defines a function whose positional-only parameter shadows a guard hook, then invokes protected operations inside that function to bypass policy checks.

python
# Illustrative pattern — positional-only parameter shadows guard hook
# Vulnerable code accepted by RestrictedPython < 8.3
def exploit(_getattr_, /, target):
    # _getattr_ is now the caller-supplied value, not the injected guard,
    # so attribute access inside this scope bypasses the policy.
    return target.__class__.__bases__
python
# Patch applied in transformer.py (RestrictedPython 8.3)
# Source: https://github.com/zopefoundation/RestrictedPython/commit/3737596ec9f28c34a073cc845bd2f4c0a80cb671
    def check_function_argument_names(self, node):
        for arg in node.args.posonlyargs:
            self.check_name(node, arg.arg)

        for arg in node.args.args:
            self.check_name(node, arg.arg)

The fix extends check_name() coverage to posonlyargs, ensuring positional-only parameters cannot begin with an underscore or match reserved guard names.

Detection Methods for CVE-2026-55830

Indicators of Compromise

  • RestrictedPython source containing function definitions with positional-only parameters (a / in the argument list) whose names begin with an underscore.
  • Function signatures declaring parameters named _getattr_, _getitem_, _write_, or _print_ before a / separator.
  • Unexpected attribute traversal, __class__ or __bases__ access, or writes to protected objects originating from user-submitted scripts.

Detection Strategies

  • Perform static review of stored RestrictedPython artifacts (Zope Script (Python) objects, DTML, custom templates) for positional-only parameters with underscore-prefixed names.
  • Compare deployed RestrictedPython package metadata against version 8.3 using inventory queries against Python environments.
  • Instrument the embedding application to log invocations of the injected guard hooks and alert when protected operations execute without a corresponding guard call.

Monitoring Recommendations

  • Audit content-authoring privileges to identify which principals can submit RestrictedPython code, and monitor edits made by those accounts.
  • Enable process and file telemetry on application servers hosting Zope, Plone, or other RestrictedPython consumers to capture unexpected child processes or file writes following sandbox execution.
  • Track imports of RestrictedPython at runtime and correlate with the installed version reported by the package manager.

How to Mitigate CVE-2026-55830

Immediate Actions Required

  • Upgrade RestrictedPython to version 8.3 or later on every host that embeds the library.
  • Inventory all RestrictedPython consumers (Zope, Plone, custom applications) and confirm they resolve to the patched release.
  • Review recently added or modified user scripts for the shadowing pattern described above and quarantine suspicious content until reviewed.
  • Restrict the set of accounts permitted to author RestrictedPython code to the minimum required.

Patch Information

The vulnerability is fixed in RestrictedPython 8.3. The upstream fix extends check_function_argument_names() to validate node.args.posonlyargs. See the GitHub Security Advisory GHSA-ffg3-p8fm-mjx2 and the upstream commit 3737596 for full details.

Workarounds

  • If patching is delayed, add a pre-compilation lint step that rejects any submitted source whose AST contains posonlyargs entries with names beginning with an underscore.
  • Temporarily revoke write access to script objects for all non-administrative accounts until the upgrade is completed.
  • Where feasible, disable execution of user-authored Python scripts in production until RestrictedPython 8.3 is deployed.
bash
# Upgrade RestrictedPython to the patched release
pip install --upgrade 'RestrictedPython>=8.3'

# Verify the installed version
python -c "import RestrictedPython; print(RestrictedPython.__version__)"

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.