RestrictedPython vulnerable to arbitrary code execution via stack frame sandbox escape
Description
RestrictedPython fails to restrict stack frame access via generators, allowing sandbox escape and potential arbitrary code execution.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
RestrictedPython fails to restrict stack frame access via generators, allowing sandbox escape and potential arbitrary code execution.
Vulnerability
Analysis
RestrictedPython is a tool that defines a subset of Python to allow untrusted code execution in a trusted environment. Prior to versions 6.1 and 5.3, it did not properly check access to stack frames and their attributes [1]. Stack frames are accessible within generators and generator expressions, which are permitted in RestrictedPython. An attacker with access to a RestrictedPython environment can craft code that retrieves the current stack frame inside a generator and then traverse the stack beyond the RestrictedPython invocation boundary, escaping the sandbox [1][2].
Exploitation
To exploit this vulnerability, an attacker must have the ability to write and execute Python code within a RestrictedPython environment. This is typically a non-default configuration, for example in Zope or Plone deployments where administrators allow untrusted users to create or edit objects such as Script (Python), DTML Method, DTML Document, or Zope Page Template [1]. The attack does not require authentication beyond the ability to submit restricted code. By using generator expressions or generators, the attacker can access the gi_frame attribute and then walk the stack using f_back to reach frames outside the restricted execution context [2].
Impact
Successful exploitation allows an attacker to break out of the restricted sandbox and potentially execute arbitrary code in the Python interpreter [1]. This could lead to full compromise of the host application, including data exfiltration, privilege escalation, or further attacks on the underlying system.
Mitigation
The issue is fixed in RestrictedPython versions 6.1 and 5.3 [1]. The fix restricts access to attributes related to stack frames, tracebacks, code objects, generators, and coroutines, as defined in the INSPECT_ATTRIBUTES list in the transformer [2]. Users should upgrade to these versions or later. As a workaround, administrators can disable untrusted user access to the script editing features in Zope/Plone if upgrading is not immediate [1].
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
RestrictedPythonPyPI | < 5.3 | 5.3 |
RestrictedPythonPyPI | >= 6.0a1.dev0, < 6.1 | 6.1 |
restrictedpythonPyPI | < 5.3 | 5.3 |
Affected products
2- Range: >= 6.0a1.dev0, < 6.1
Patches
3f9ef13be3f38- prepare release 5.3
2 files changed · +2 −2
CHANGES.rst+1 −1 modified@@ -1,7 +1,7 @@ Changes ======= -5.3 (unreleased) +5.3 (2023-07-08) ---------------- - Restrict access to some attributes accessible via the ``inspect`` module.
setup.py+1 −1 modified@@ -32,7 +32,7 @@ def read(*rnames): setup( name='RestrictedPython', - version='5.3.dev0', + version='5.3', url='https://github.com/zopefoundation/RestrictedPython', license='ZPL 2.1', description=(
311f2f7eee49- prepare release 6.1
2 files changed · +2 −2
CHANGES.rst+1 −1 modified@@ -1,7 +1,7 @@ Changes ======= -6.1 (unreleased) +6.1 (2023-07-08) ---------------- - Restrict access to some attributes accessible via the ``inspect`` module.
setup.py+1 −1 modified@@ -32,7 +32,7 @@ def read(*rnames): setup( name='RestrictedPython', - version='6.1.dev0', + version='6.1', url='https://github.com/zopefoundation/RestrictedPython', license='ZPL 2.1', description=(
c8eca66ae490Merge pull request from GHSA-wqc8-x2pr-7jqh
4 files changed · +99 −0
CHANGES.rst+5 −0 modified@@ -15,6 +15,11 @@ Features - Allow to use the package with Python 3.12 -- Caution: No security audit has been done so far. +Fixes ++++++ + +- Restrict access to some attributes accessible via the ``inspect`` module. + 6.0 (2022-11-03) ----------------
docs/contributing/index.rst+1 −0 modified@@ -64,6 +64,7 @@ To do so: All AST Nodes without an explicit ``visit_<AST Node>`` method, are denied by default. So the usage of this expression and functionality is not allowed. +* Check the documentation for `inspect <https://docs.python.org/3/library/inspect.html>`_ and adjust the ``transformer.py:INSPECT_ATTRIBUTES`` list. * Add a corresponding changelog entry. * Additionally modify ``.meta.toml`` and run the ``meta/config`` script (for details see: https://github.com/mgedmin/check-python-versions) to update the following files:
src/RestrictedPython/transformer.py+33 −0 modified@@ -63,6 +63,32 @@ 'breakpoint', ]) +# inspect attributes. See also +# https://docs.python.org/3/library/inspect.html +INSPECT_ATTRIBUTES = frozenset([ + # traceback + "tb_frame", + "tb_next", + # code + "co_code", + # frame + "f_back", + "f_builtins", + "f_code", + "f_globals", + "f_locals", + "f_trace", + # generator + "gi_frame", + "gi_code", + "gi_yieldfrom", + # coroutine + "cr_await", + "cr_frame", + "cr_code", + "cr_origin", +]) + # When new ast nodes are generated they have no 'lineno', 'end_lineno', # 'col_offset' and 'end_col_offset'. This function copies these fields from the @@ -844,6 +870,13 @@ def visit_Attribute(self, node): '"{name}" is an invalid attribute name because it ends ' 'with "__roles__".'.format(name=node.attr)) + if node.attr in INSPECT_ATTRIBUTES: + self.error( + node, + f'"{node.attr}" is a restricted name,' + ' that is forbidden to access in RestrictedPython.', + ) + if isinstance(node.ctx, ast.Load): node = self.node_contents_visit(node) new_node = ast.Call(
tests/transformer/test_inspect.py+60 −0 added@@ -0,0 +1,60 @@ +from RestrictedPython import compile_restricted_exec + + +def test_get_inspect_frame_on_generator(): + source_code = """ +generator = (statement.gi_frame for _ in (1,)) +generator_element = [elem for elem in generator][0] + +""" + result = compile_restricted_exec(source_code) + assert result.errors == ( + 'Line 2: "gi_frame" is a restricted name, ' + 'that is forbidden to access in RestrictedPython.', + ) + + +def test_get_inspect_frame_back_on_generator(): + source_code = """ +generator = (statement.gi_frame.f_back.f_back for _ in (1,)) +generator_element = [elem for elem in generator][0] + +""" + result = compile_restricted_exec(source_code) + assert result.errors == ( + 'Line 2: "f_back" is a restricted name, ' + 'that is forbidden to access in RestrictedPython.', + 'Line 2: "f_back" is a restricted name, ' + 'that is forbidden to access in RestrictedPython.', + 'Line 2: "gi_frame" is a restricted name, ' + 'that is forbidden to access in RestrictedPython.', + ) + + +def test_call_inspect_frame_on_generator(): + source_code = """ +generator = None +frame = None + +def test(): + global generator, frame + frame = g.gi_frame.f_back.f_back + yield frame + +generator = test() +generator.send(None) +os = frame.f_builtins.get('__import__')('os') + +result = os.listdir('/') +""" + result = compile_restricted_exec(source_code) + assert result.errors == ( + 'Line 7: "f_back" is a restricted name, ' + 'that is forbidden to access in RestrictedPython.', + 'Line 7: "f_back" is a restricted name, ' + 'that is forbidden to access in RestrictedPython.', + 'Line 7: "gi_frame" is a restricted name, ' + 'that is forbidden to access in RestrictedPython.', + 'Line 12: "f_builtins" is a restricted name, ' + 'that is forbidden to access in RestrictedPython.', + )
Vulnerability mechanics
Root cause
"RestrictedPython does not restrict access to stack frames and their attributes, allowing a generator to walk the stack beyond the sandbox boundary."
Attack vector
An attacker with the ability to write Python code inside a RestrictedPython environment can craft a generator or generator expression that accesses the current stack frame. By walking the stack frame chain, the attacker can escape the RestrictedPython sandbox boundary and reach the unrestricted Python interpreter. This allows arbitrary code execution outside the sandbox. The attack requires that the administrator has enabled untrusted users to create or edit objects such as ``Script (Python)``, ``DTML Method``, ``DTML Document``, or ``Zope Page Template``, which is a non-default configuration [CWE-913].
Affected code
The vulnerability lies in RestrictedPython's failure to restrict access to stack frames and their attributes. Stack frames are accessible within generators and generator expressions, which are permitted inside the sandbox. The patch restricts access to attributes accessible via the ``inspect`` module, but the exact code paths are not detailed in the supplied patches.
What the fix does
The fix restricts access to attributes accessible via the ``inspect`` module, which is the vector used to obtain stack frames. By blocking these attributes, attackers can no longer use the ``inspect`` module to retrieve the current stack frame from within a generator. The patches in versions 5.3 [patch_id=1640687] and 6.1 [patch_id=1640686] both apply the same restriction. The underlying commit [patch_id=1707204] implements the actual code change that closes the sandbox escape.
Preconditions
- configThe administrator must allow untrusted users to create or edit Python script objects (Script (Python), DTML Method, DTML Document, or Zope Page Template) in a RestrictedPython environment.
- inputThe attacker must have the ability to write and execute Python code within the RestrictedPython sandbox.
Generated on May 23, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/advisories/GHSA-wqc8-x2pr-7jqhghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2023-37271ghsaADVISORY
- github.com/pypa/advisory-database/tree/main/vulns/restrictedpython/PYSEC-2023-118.yamlghsaWEB
- github.com/zopefoundation/RestrictedPython/commit/c8eca66ae49081f0016d2e1f094c3d72095ef531ghsax_refsource_MISCWEB
- github.com/zopefoundation/RestrictedPython/security/advisories/GHSA-wqc8-x2pr-7jqhghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.