🛡️ CVE-2026-57120 — praisonaiagents

⚪ Unknown ✅ No Known Exploit CWE-693 OSV
N/A
CVSS Score
0 Low4 Medium7 High9 Critical10

Description

PraisonAI: execute_code sandbox bypass: str.format C-level attribute access reads every blocklisted dunder

Summary

The execute_code tool's subprocess sandbox advertises a three-layer defense (AST validation, text-pattern blocklist, restricted __builtins__). In sandbox mode (the default) only two layers are active — the text-pattern blocklist is skipped — and both remaining layers are bypassed by combining two CPython semantics:

1. Runtime string assembly. The AST validator (src/praisonai-agents/praisonaiagents/tools/python_tools.py:75) enumerates blocked dunder names against ast.Attribute.attr, ast.Call.func.id, and ast.Constant string-substring. Names assembled at runtime (e.g. "_"*2 + "class" + "_"*2) appear in the AST as multiple short ast.Constant nodes, none containing a blocked substring, so the static check passes.

2. C-level attribute access via format-spec. str.format / str.format_map resolve dotted field references through CPython's internal PyObject_GetAttr (do_string_formatget_field). This C path never consults the Python-level getattr binding. The sandbox's _safe_getattr wrapper (python_tools.py:221) is installed only as the getattr name in safe_builtins, so any C-level attribute access — including format-spec field resolution — sidesteps it. format/format_map are also absent from _SANDBOX_BLOCKED_CALLS (python_tools.py:56).

Combined, this yields an arbitrary read primitive over every blocklisted attribute (__class__, __qualname__, __bases__, __base__, function __globals__, __dict__, …).

Affected code

| File | Lines | Symbol | Role |

|---|---|---|---|

| src/praisonai-agents/praisonaiagents/tools/python_tools.py | 39–54 | _SANDBOX_BLOCKED_ATTRS | The blocklist the bypass renders unreachable |

| src/praisonai-agents/praisonaiagents/tools/python_tools.py | 56–60 | _SANDBOX_BLOCKED_CALLS | Missing entries: format, format_map |

| src/praisonai-agents/praisonaiagents/tools/python_tools.py | 75–102 | _validate_code_ast | Static check, blind to runtime string assembly |

| src/praisonai-agents/praisonaiagents/tools/python_tools.py | 221–226 | _safe_getattr | Wraps Python-level getattr only; C-level access bypasses |

| src/praisonai-agents/praisonaiagents/tools/python_tools.py | 352 | execute_code | Entry point; gated by @require_approval(risk_level="critical") |

Reproducer

```python

import os

os.environ["PRAISONAI_AUTO_APPROVE"] = "true"

from praisonaiagents.tools.python_tools import execute_code

payload = '''

und = "_" * 2 # "__" assembled at runtime

key1 = und + "class" + und # "__class__"

key2 = und + "qualname" + und # "__qualname__"

fmt_class = "{0." + key1 + "}"

fmt_qual2 = "{0." + key1 + "." + key2 + "}"

print("LEAK_CLASS=" + fmt_class.format(()))

print("LEAK_QUAL2=" + fmt_qual2.format(()))

'''

print(execute_code(payload, sandbox_mode="sandbox", timeout=15))

```

Observed: stdout = LEAK_CLASS=<class 'tuple'> / LEAK_QUAL2=tuple, success: true, no security error. Both __class__ (one hop) and __class__.__qualname__ (two hops) — all blocklisted — are read.

Trust boundary

The @require_approval(risk_level="critical") gate is bypassed when PRAISONAI_AUTO_APPROVE is set (verified: require_approval short-circuits on is_env_auto_approve()). That variable is set by the project's FULL_AUTO autonomy mode, the bots-CLI launchers, and the project's own issue-triage CI workflow — postures where the agent reaches execute_code with no human approval. The payload then arrives via any LLM-visible surface (user message, retrieved document, tool/web/MCP output) and the tool-call machinery passes it as the code argument.

Relationship to GHSA-4mr5-g6f9-cfrh

The code's own comment at python_tools.py:46 cites GHSA-4mr5-g6f9-cfrh, which added __self__ to the blocklist to stop C-builtins leaking builtins via func.__self__. This finding does not bypass that single entry — it bypasses the entire blocklist, because format-spec attribute resolution never consults the blocklist or _safe_getattr. "{0.__self__}".format(print) would leak __self__ regardless of the blocklist. Same defense surface, different mechanism; the GHSA-4mr5 fix does not mitigate this.

Scope (read primitive only)

This reports the read primitive. Turning the read into in-process execution requires a callable bridge; the obvious one (string.Formatter().get_field() returning the live object) is not directly reachable because import string is blocked at the AST layer (no ast.Import). Other bridges may exist; a full execution chain is not claimed here. If one is found, severity rises to ~8.8 (the subprocess has no seccomp/setrlimit/syscall filtering).

Suggested fix

1. Add format, format_map to _SANDBOX_BLOCKED_CALLS (blocks the calls at the AST layer; cost: also blocks benign str.format).

2. Or replace str in `safe_built

How this vulnerability can be exploited

This issue can be reached over the network, attack complexity is low, an attacker needs low-level privileges on the target. No user interaction is required. The scope is unchanged, so the impact stays within the vulnerable component. Rated impact: confidentiality high, integrity none, availability none.

Weakness class

CVE-2026-57120 is classified as CWE-693: Protection Mechanism Failure. A protection exists but does not cover the case at hand, so it can be worked around.

Affected software

CVE-2026-57120 is recorded against 1 package.

  • praisonaiagents (fixed in 1.6.59)

Timeline and source

Published on 18 June 2026 and last revised on 23 July 2026. No public exploit is currently recorded for this entry. Record sourced from OSV.

References

github.com (Web)
github.com (Package)

Details

Severity Unknown
CVSS Score N/A
CVSS Vector CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
CWE CWE-693
Public Exploit ✅ No
Source OSV
Published 2026-06-18
Updated 2026-08-12
Modified 2026-07-23
Fix URL N/A

Affected Packages

Software From version Fixed in
praisonaiagents 1.6.59

Similar Threats

Free Vulnerability Check

Is your site affected by CVE-2026-57120?

BotEraser helps you identify potentially vulnerable plugins and themes by checking your installation against CVE-2026-57120 and other known CVE records.

Scan My Site Free →

No credit card required  ·  Results in minutes

ⓘ Data Notice: The information presented above has been compiled from publicly available internet sources. Boteraser aggregates this data solely for informational purposes and does not independently classify, evaluate, or endorse any findings about the vulnerabilities listed. The accuracy and completeness of this information is the sole responsibility of the original publishers. Boteraser and its operators accept no liability for any decisions made based on this data.