Executive Summary
Nine distinct vulnerabilities have been disclosed across two PyPI packages that together constitute the PraisonAI multi-agent framework: praisonai (six CVEs) and praisonaiagents (three CVEs). CNA-submitted CVSS scores range from 7.7 to 10.0; four vulnerabilities carry Critical ratings. Any organisation running PraisonAI in a networked or production context should treat this cluster as high priority.
The highest-severity finding is CVE-2026-34938 (CNA-submitted CVSS 10.0) in praisonaiagents, where Python's execute_code() sandbox can be escaped by passing a str subclass with an overridden startswith() method, entirely defeating the pattern-based block list without authentication. Vendor-published proof-of-concept code is available for four of the nine CVEs: CVE-2026-34935 (GHSA-9gm9-c8mq-vq7m), CVE-2026-34938 (GHSA-6vh2-h83c-9294), CVE-2026-34937 (GHSA-w37c-qqfp-c67f), and CVE-2026-34955 (GHSA-r4f2-3m54-pp7q). The most immediately exploitable is CVE-2026-34935 (CNA-submitted CVSS 9.8) in praisonai, where the --mcp CLI argument is passed unsanitised through shlex.split() to anyio.open_process(), permitting arbitrary OS command execution when an attacker has untrusted influence over that argument.
Remediation requires two separate package upgrades. A single pip install command does not resolve all nine CVEs. Operators must upgrade praisonai to 4.5.97 or later and praisonaiagents to 1.5.95 or later as independent operations. All fix versions have been verified as present in the PyPI release index as of 2026-04-05 (https://pypi.org/pypi/praisonai/json; https://pypi.org/pypi/praisonaiagents/json).
RAXE assessment: The cluster density — nine CVEs across five CWE classes in two co-maintained packages, all disclosed within the same two-day window — is consistent with a coordinated private disclosure or internal security audit rather than nine independent reporters. The breadth of vulnerability classes (injection, sandbox bypass, authentication failure, SSRF) is more indicative of systematic security review than opportunistic discovery.
Risk Rating
| Dimension | Rating | Detail |
|---|---|---|
| Severity | CRITICAL | Four Critical CVEs (CVSS 9.1–10.0); five High CVEs (CVSS 7.7–8.8) |
| Urgency | HIGH | Public PoC exists for CVE-2026-34935; cluster covers authentication bypass |
| Scope | ECOSYSTEM | Both praisonai and praisonaiagents packages affected |
| Confidence | HIGH | All CVEs verified on NVD; fix versions verified on PyPI; PoC sourced from GitHub Security Advisory |
| Business Impact | HIGH | Potential for unauthenticated RCE, full database compromise, and cloud metadata exfiltration in exposed deployments |
Affected Products
Package: praisonai (PyPI) - 6 CVEs
| CVE | CNA-Submitted CVSS | Severity | Fixed In |
|---|---|---|---|
CVE-2026-34935 |
9.8 | CRITICAL | 4.5.69 |
CVE-2026-34934 |
9.8 | CRITICAL | 4.5.90 |
CVE-2026-34952 |
9.1 | CRITICAL | 4.5.97 |
CVE-2026-34953 |
9.1 | CRITICAL | 4.5.97 |
CVE-2026-34955 |
8.8 | HIGH | 4.5.97 |
CVE-2026-34936 |
7.7 | HIGH | 4.5.90 |
Sources: NVD (https://nvd.nist.gov/vuln/detail/CVE-2026-34934, https://nvd.nist.gov/vuln/detail/CVE-2026-34935, https://nvd.nist.gov/vuln/detail/CVE-2026-34936, https://nvd.nist.gov/vuln/detail/CVE-2026-34952, https://nvd.nist.gov/vuln/detail/CVE-2026-34953, https://nvd.nist.gov/vuln/detail/CVE-2026-34955); GitLab GLAD (https://advisories.gitlab.com/pkg/pypi/praisonai/CVE-2026-34934/, https://advisories.gitlab.com/pkg/pypi/praisonai/CVE-2026-34936/).
Package: praisonaiagents (PyPI) - 3 CVEs
| CVE | CNA-Submitted CVSS | Severity | Fixed In |
|---|---|---|---|
CVE-2026-34938 |
10.0 | CRITICAL | 1.5.90 |
CVE-2026-34937 |
7.8 | HIGH | 1.5.90 |
CVE-2026-34954 |
8.6 | HIGH | 1.5.95 |
Sources: NVD (https://nvd.nist.gov/vuln/detail/CVE-2026-34937, https://nvd.nist.gov/vuln/detail/CVE-2026-34938, https://nvd.nist.gov/vuln/detail/CVE-2026-34954); GitLab GLAD (https://advisories.gitlab.com/pkg/pypi/praisonaiagents/CVE-2026-34954/).
Note on CVSS provenance: All scores above are CNA-submitted values present in NVD at the time of publication (NVD vulnStatus: Received for all nine CVEs). NVD's independent analysis has not yet been completed. RAXE reproduces the CNA-submitted scores as the best available data; scores may be revised when NVD analysis is complete.
Am I Affected?
- Check whether your environment installs
praisonaiorpraisonaiagentsfrom PyPI - Check installed versions:
pip show praisonai praisonaiagents praisonaiversions prior to 4.5.97 are vulnerable to at least one CVE in this clusterpraisonaiagentsversions prior to 1.5.95 are vulnerable to at least one CVE in this cluster- Both packages must be checked independently — upgrading one does not address vulnerabilities in the other
Attack Flow
ATTACKER
|
+-- (CVE-2026-34935) Influence --mcp CLI arg
| -> shlex.split() -> anyio.open_process() -> OS COMMAND EXECUTION
|
+-- (CVE-2026-34938) Pass BypassStr to execute_code()
| -> startswith() returns False -> block list bypassed -> OS COMMAND EXECUTION
|
+-- (CVE-2026-34952) Connect to /ws without credentials
| -> Agent runtime interaction (no auth check)
| +-- (CVE-2026-34953) Present fabricated token
| -> validate_token() returns True -> AUTH BYPASS
|
+-- (CVE-2026-34934) Write malicious thread ID via update_thread
| -> get_all_user_threads() executes stored payload -> SQL INJECTION
|
+-- (CVE-2026-34936) Supply api_base to passthrough() (auth required: PR:L)
| -> httpx.Client.request(attacker-controlled URL) -> SSRF
|
+-- (CVE-2026-34937) Supply metacharacters to run_python()
| -> shell=True -> SHELL INJECTION
|
+-- (CVE-2026-34954) Supply internal URL to download_file()
| -> httpx.stream(url, follow_redirects=True) -> SSRF
|
+-- (CVE-2026-34955) Encode payload to evade SubprocessSandbox patterns
-> shell=True interprets encoded payload -> SANDBOX BYPASS
Technical Details
1. CVE-2026-34938 - execute_code() Sandbox Bypass via str Subclass (CNA-Submitted CVSS 10.0 CRITICAL)
Package: praisonaiagents | CWE: CWE-693 | Fixed: 1.5.90
The execute_code() function in praisonaiagents uses a pattern-based block list to screen submitted code for disallowed constructs. The block-list check calls startswith() on the submitted string object to test each blocked pattern. Python's str.startswith() is a normal, overrideable method.
An attacker who controls the argument passed to execute_code() can supply a str subclass whose startswith() method unconditionally returns False, regardless of content. Because the block-list loop calls startswith() and receives False for every blocked pattern, the check concludes that no disallowed construct is present. The underlying string still contains the disallowed payload, which is then executed, granting full access to the process user's OS environment with no authentication required.
The vendor advisory GHSA-6vh2-h83c-9294 includes a full proof-of-concept demonstrating sandbox escape via a str subclass with overridden startswith(), walking the class hierarchy through __mro__ and __subclasses__ to reach subprocess.Popen and execute arbitrary OS commands (GHSA-6vh2-h83c-9294).
RAXE assessment: CVSS 10.0 reflects the complete absence of authentication or privilege requirements — only the ability to influence an argument passed to execute_code() is needed. In agent frameworks where execute_code() is exposed as a tool callable by a language model responding to user prompts, an attacker with influence over the prompt can trigger this path. The escape is complete: no sandbox boundary survives.
2. CVE-2026-34935 - MCP CLI Command Injection (CNA-Submitted CVSS 9.8 CRITICAL)
Package: praisonai | CWE: CWE-78 | Fixed: 4.5.69 | Public PoC: yes
The --mcp CLI argument is passed directly to shlex.split() and forwarded through the call chain with no validation at any hop:
cli/features/mcp.py:61
-> praisonaiagents/mcp/mcp.py:345
-> mcp/client/stdio/__init__.py:253
-> anyio.open_process() <- sink
The first token of the argument becomes the subprocess command name, permitting arbitrary OS command execution as the process user.
Precondition: An attacker must have untrusted influence over the --mcp CLI argument. In typical deployment this means the argument originates from user-supplied input, configuration loaded from an untrusted source, or an indirect prompt injection reaching CLI dispatch logic.
Public proof-of-concept (sourced from GHSA-9gm9-c8mq-vq7m, tested against praisonai 4.5.48 per the advisory author):
praisonai --mcp "bash -c 'id > /tmp/pwned'"
cat /tmp/pwned
# uid=1000(...) gid=1000(...) groups=1000(...)
Sources: GHSA-9gm9-c8mq-vq7m via OSV.dev (https://osv.dev/vulnerability/GHSA-9gm9-c8mq-vq7m); GitHub Security Advisory (https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-9gm9-c8mq-vq7m).
The fix in commit 47bff65413beaa3c21bf633c1fae4e684348368c (v4.5.69) introduces a command allowlist (ALLOWED_MCP_COMMANDS) containing approximately 20 entries — including npx, uvx, node, python, python3, uv, pipx, deno, bun, and docker (plus Windows .exe variants) — rejecting any first token not in the set before the call chain is entered. Note that docker is included in the allowlist; deployments where docker is in scope should assess whether this presents an acceptable residual risk. Source: fix commit (https://github.com/MervinPraison/PraisonAI/commit/47bff65413beaa3c21bf633c1fae4e684348368c).
RAXE assessment: The public PoC lowers the exploitation barrier significantly. The CVE-2026-34935 EPSS percentile (24.5th at time of publication) is expected to rise as the advisory circulates. Organisations running PraisonAI with any user-controlled input path to --mcp should treat this as the highest-urgency remediation item.
3. CVE-2026-34934 - Second-Order SQL Injection in get_all_user_threads (CNA-Submitted CVSS 9.8 CRITICAL)
Package: praisonai | CWE: CWE-89 | Fixed: 4.5.90
The get_all_user_threads() function constructs raw SQL queries using Python f-strings with thread IDs read back from the database. A thread ID previously written by an attacker via update_thread is included verbatim in the query string without parameterisation.
This is a second-order (stored) injection pattern: the injection vector is the write path (update_thread) and the trigger is the read path (get_all_user_threads). The separation between write and read means input validation at the write step is insufficient — the malicious payload is stored and replayed at query time, granting full database read and write access depending on the database engine and configured user privileges. No public proof-of-concept was identified in advisory sources reviewed. Sources: GitLab GLAD (https://advisories.gitlab.com/pkg/pypi/praisonai/CVE-2026-34934/); NVD (https://nvd.nist.gov/vuln/detail/CVE-2026-34934).
4. CVE-2026-34952 - WebSocket Endpoints Missing Authentication (CNA-Submitted CVSS 9.1 CRITICAL)
Package: praisonai | CWE: CWE-306 | Fixed: 4.5.97
The /ws WebSocket endpoint and the /info REST endpoint are accessible without any authentication check. Any party that can reach the server can connect and interact with the agent runtime. No public proof-of-concept was identified in advisory sources reviewed. Source: NVD (https://nvd.nist.gov/vuln/detail/CVE-2026-34952).
RAXE assessment: CVE-2026-34952 and CVE-2026-34953 (below) interact. CVE-2026-34952 removes authentication from the WebSocket endpoint entirely; CVE-2026-34953 undermines token validation for endpoints that nominally require a token. Together they represent a near-total collapse of the authentication layer for the agent runtime API in affected versions.
5. CVE-2026-34953 - OAuthManager.validate_token() Returns True for Unknown Tokens (CNA-Submitted CVSS 9.1 CRITICAL)
Package: praisonai | CWE: CWE-863 | Fixed: 4.5.97
OAuthManager.validate_token() returns True for any token value it does not recognise, rather than False (deny by default). This inverts the expected security invariant: fabricated, expired, and malformed tokens are all accepted as valid. Any caller presenting any token string — including a randomly generated value — passes the authentication gate. No public proof-of-concept was identified in advisory sources reviewed. Source: NVD (https://nvd.nist.gov/vuln/detail/CVE-2026-34953).
6. CVE-2026-34955 - SubprocessSandbox shell=True Bypass via Pattern Matching (CNA-Submitted CVSS 8.8 HIGH)
Package: praisonai | CWE: CWE-78 | Fixed: 4.5.97
SubprocessSandbox attempts to block dangerous shell constructs by checking the command string against a set of patterns before execution. However, the underlying subprocess invocation uses shell=True, which means the shell processes the command after the pattern check. Any block-list approach operating on the raw command string prior to shell expansion is inherently defeatable because the block list and the shell interpret the string differently — encoding, quoting, variable interpolation, and shell-specific syntax all provide potential bypass paths. The root cause is the use of shell=True itself. The vendor advisory GHSA-r4f2-3m54-pp7q includes a proof-of-concept demonstrating sandbox escape by invoking sh -c '<blocked_command>' to bypass the pattern-based block list, which fails to intercept shell built-ins passed as arguments to sh (GHSA-r4f2-3m54-pp7q).
7. CVE-2026-34954 - FileTools.download_file() SSRF via Unvalidated URL (CNA-Submitted CVSS 8.6 HIGH)
Package: praisonaiagents | CWE: CWE-918 | Fixed: 1.5.95
FileTools.download_file() validates the destination path on the local filesystem but performs no validation on the url parameter. The URL is passed directly to httpx.stream(url, follow_redirects=True). An attacker who controls the URL can reach any host accessible from the server, including cloud instance metadata services (e.g., 169.254.169.254) and internal network services. The follow_redirects=True flag additionally enables open-redirect chains — an attacker may supply a URL pointing to an externally accessible redirect that terminates at an internal address. No public proof-of-concept was identified in advisory sources reviewed. Sources: GitLab GLAD (https://advisories.gitlab.com/pkg/pypi/praisonaiagents/CVE-2026-34954/); NVD (https://nvd.nist.gov/vuln/detail/CVE-2026-34954).
8. CVE-2026-34937 - run_python() shell=True Command Injection (CNA-Submitted CVSS 7.8 HIGH)
Package: praisonaiagents (per GHSA-w37c-qqfp-c67f package field and fix version 1.5.90) | CWE: CWE-78 | Fixed: 1.5.90
Source attribution note: The NVD description text for CVE-2026-34937 refers to run_python() in praisonai, while the GHSA package field and the 1.5.x fix version series both indicate the affected package is praisonaiagents. This advisory follows the GHSA package attribution as the more specific source; the NVD description may use the project umbrella name rather than the precise PyPI package name (NVD, GHSA-w37c-qqfp-c67f).
run_python() invokes subprocesses with shell=True. When shell=True is used, the shell interprets the entire command string, meaning any shell metacharacter — ;, &&, |, $(), backticks — present in a caller-controlled argument is processed by the shell rather than treated as a literal argument. Note: CVE-2026-34937 and CVE-2026-34935 are distinct injection paths in different components; the attack surface and trigger mechanism differ depending on agent configuration. The vendor advisory GHSA-w37c-qqfp-c67f includes a proof-of-concept demonstrating shell injection via $(id > /tmp/injected) passed to run_python(), exploiting incomplete escaping that neutralises backslashes and quotes but not $() and backtick substitutions (GHSA-w37c-qqfp-c67f).
9. CVE-2026-34936 - SSRF via api_base in passthrough() Fallback (CNA-Submitted CVSS 7.7 HIGH)
Package: praisonai | CWE: CWE-918 | Fixed: 4.5.90 | Authentication required: Yes (CVSS PR:L)
passthrough() and its async variant apassthrough() accept a caller-controlled api_base parameter. When the primary litellm call path raises AttributeError, the fallback path concatenates api_base with a hardcoded endpoint path and passes the result directly to httpx.Client.request(). No URL scheme validation, private IP filtering, or domain allowlist is applied. A low-privilege authenticated caller can redirect outbound HTTP requests to any host reachable from the server. Unauthenticated exploitation is not possible — a valid low-privilege session is required. No public proof-of-concept was identified in advisory sources reviewed. Sources: GitLab GLAD (https://advisories.gitlab.com/pkg/pypi/praisonai/CVE-2026-34936/); NVD (https://nvd.nist.gov/vuln/detail/CVE-2026-34936).
Confidence and Validation
Assessment Confidence: HIGH
| Aspect | Status | Detail |
|---|---|---|
| Vendor advisory | Confirmed | GitHub Security Advisory GHSA-9gm9-c8mq-vq7m published for CVE-2026-34935; GitLab GLAD entries for CVE-2026-34934, CVE-2026-34936, CVE-2026-34954 |
| CVEs assigned | Confirmed | All nine CVEs present in NVD (vulnStatus: Received; CNA-submitted scores) |
| Public PoC available | Partial | Vendor-published PoC confirmed for 4 of 9 CVEs: CVE-2026-34935 (GHSA-9gm9-c8mq-vq7m), CVE-2026-34938 (GHSA-6vh2-h83c-9294), CVE-2026-34937 (GHSA-w37c-qqfp-c67f), CVE-2026-34955 (GHSA-r4f2-3m54-pp7q); no public PoC identified for the remaining five |
| Patches available | Confirmed | Fix versions verified on PyPI as of 2026-04-05 |
| Exploited in wild | Not observed | No CISA KEV listing; EPSS percentiles consistent with fresh disclosure |
Exploitation Prediction (EPSS)
EPSS scores from FIRST.org (https://api.first.org/data/v1/epss?cve=CVE-2026-34934,CVE-2026-34935,CVE-2026-34936,CVE-2026-34937,CVE-2026-34938,CVE-2026-34952,CVE-2026-34953,CVE-2026-34954,CVE-2026-34955), retrieved 2026-04-05:
| CVE | EPSS Score | Percentile | Notes |
|---|---|---|---|
CVE-2026-34938 |
0.00100 | 27.8th | CVSS 10.0; vendor PoC published (GHSA-6vh2-h83c-9294) |
CVE-2026-34935 |
0.00083 | 24.5th | Vendor PoC published (GHSA-9gm9-c8mq-vq7m) |
CVE-2026-34934 |
0.00048 | 14.9th | — |
CVE-2026-34952 |
0.00038 | 11.5th | — |
CVE-2026-34954 |
0.00032 | 9.1th | — |
CVE-2026-34953 |
0.00030 | 8.6th | — |
CVE-2026-34936 |
0.00028 | 8.0th | — |
CVE-2026-34937 |
0.00027 | 7.6th | Vendor PoC published (GHSA-w37c-qqfp-c67f) |
CVE-2026-34955 |
0.00020 | 5.4th | Vendor PoC published (GHSA-r4f2-3m54-pp7q) |
RAXE assessment: EPSS scores are low across the cluster, consistent with freshly disclosed CVEs before weaponisation infrastructure develops. CVE-2026-34938 leads with a vendor-published PoC (GHSA-6vh2-h83c-9294) and a CVSS 10.0 / CWE-693 co-occurrence that the EPSS model weights heavily. CVE-2026-34935 ranks second; the existence of a step-by-step public PoC in GHSA-9gm9-c8mq-vq7m may drive its percentile upward over the next 30 days as the advisory circulates (RAXE assessment).
Detection Signatures
Detection rules for CVE-2026-34935 (MCP CLI command injection) are included in this release. Detection rules for the remaining CVEs in the cluster require agent-runtime visibility (WebSocket traffic, SQL query logs, subprocess telemetry) that varies by deployment and are not included in this publication.
The Sigma rule detects process spawning that matches the CVE-2026-34935 exploitation pattern; the YARA rule detects the vulnerable package version in pip metadata on disk.
Sigma - CVE-2026-34935 MCP CLI Command Injection
title: PraisonAI MCP CLI Command Injection (CVE-2026-34935)
id: praisonai-mcp-cli-injection-cve-2026-34935
status: experimental
description: >
Detects process creation consistent with exploitation of CVE-2026-34935 in praisonai,
where the --mcp CLI argument is passed unsanitised to anyio.open_process().
Triggers on child processes of praisonai whose image is not in the expected allowlist.
references:
- https://nvd.nist.gov/vuln/detail/CVE-2026-34935
- https://osv.dev/vulnerability/GHSA-9gm9-c8mq-vq7m
author: RAXE Labs
date: 2026-04-05
tags:
- attack.execution
- attack.t1059
logsource:
category: process_creation
product: linux
detection:
selection:
ParentImage|endswith: '/praisonai'
Image|endswith:
- '/bash'
- '/sh'
- '/zsh'
- '/dash'
- '/curl'
- '/wget'
- '/nc'
- '/ncat'
condition: selection
falsepositives:
- Legitimate praisonai deployments that spawn shell processes as part of configured MCP tools
level: high
YARA - praisonai Vulnerable Version Detection
rule RAXE_praisonai_CVE_2026_34935_vulnerable_version
{
meta:
description = "Detects praisonai pip package metadata at a version vulnerable to CVE-2026-34935 (MCP CLI injection). Matches METADATA files where the version is 4.5.15 through 4.5.68 (per GHSA-9gm9-c8mq-vq7m affected range >= 4.5.15, <= 4.5.68; fixed in 4.5.69)."
author = "RAXE Labs"
date = "2026-04-05"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2026-34935"
severity = "HIGH"
strings:
$pkg_name = "Name: praisonai" ascii
// Versions 4.5.15 through 4.5.68 are vulnerable per GHSA-9gm9-c8mq-vq7m; 4.5.69+ is fixed.
// Note: versions below 4.5.15 are NOT affected per vendor advisory.
// Match sub-minor versions 15 through 68 (per GHSA-9gm9-c8mq-vq7m: >= 4.5.15, <= 4.5.68).
// Versions 4.5.0 through 4.5.14 are NOT affected and are excluded.
$vuln_v_15 = "Version: 4.5.15" ascii
$vuln_v_16 = "Version: 4.5.16" ascii
$vuln_v_17 = "Version: 4.5.17" ascii
$vuln_v_18 = "Version: 4.5.18" ascii
$vuln_v_19 = "Version: 4.5.19" ascii
$vuln_v_20 = "Version: 4.5.20" ascii
$vuln_v_21 = "Version: 4.5.21" ascii
$vuln_v_22 = "Version: 4.5.22" ascii
$vuln_v_23 = "Version: 4.5.23" ascii
$vuln_v_24 = "Version: 4.5.24" ascii
$vuln_v_25 = "Version: 4.5.25" ascii
$vuln_v_26 = "Version: 4.5.26" ascii
$vuln_v_27 = "Version: 4.5.27" ascii
$vuln_v_28 = "Version: 4.5.28" ascii
$vuln_v_29 = "Version: 4.5.29" ascii
$vuln_v_30 = "Version: 4.5.30" ascii
$vuln_v_31 = "Version: 4.5.31" ascii
$vuln_v_32 = "Version: 4.5.32" ascii
$vuln_v_33 = "Version: 4.5.33" ascii
$vuln_v_34 = "Version: 4.5.34" ascii
$vuln_v_35 = "Version: 4.5.35" ascii
$vuln_v_36 = "Version: 4.5.36" ascii
$vuln_v_37 = "Version: 4.5.37" ascii
$vuln_v_38 = "Version: 4.5.38" ascii
$vuln_v_39 = "Version: 4.5.39" ascii
$vuln_v_40 = "Version: 4.5.40" ascii
$vuln_v_41 = "Version: 4.5.41" ascii
$vuln_v_42 = "Version: 4.5.42" ascii
$vuln_v_43 = "Version: 4.5.43" ascii
$vuln_v_44 = "Version: 4.5.44" ascii
$vuln_v_45 = "Version: 4.5.45" ascii
$vuln_v_46 = "Version: 4.5.46" ascii
$vuln_v_47 = "Version: 4.5.47" ascii
$vuln_v_48 = "Version: 4.5.48" ascii
$vuln_v_49 = "Version: 4.5.49" ascii
$vuln_v_50 = "Version: 4.5.50" ascii
$vuln_v_51 = "Version: 4.5.51" ascii
$vuln_v_52 = "Version: 4.5.52" ascii
$vuln_v_53 = "Version: 4.5.53" ascii
$vuln_v_54 = "Version: 4.5.54" ascii
$vuln_v_55 = "Version: 4.5.55" ascii
$vuln_v_56 = "Version: 4.5.56" ascii
$vuln_v_57 = "Version: 4.5.57" ascii
$vuln_v_58 = "Version: 4.5.58" ascii
$vuln_v_59 = "Version: 4.5.59" ascii
$vuln_v_60 = "Version: 4.5.60" ascii
$vuln_v_61 = "Version: 4.5.61" ascii
$vuln_v_62 = "Version: 4.5.62" ascii
$vuln_v_63 = "Version: 4.5.63" ascii
$vuln_v_64 = "Version: 4.5.64" ascii
$vuln_v_65 = "Version: 4.5.65" ascii
$vuln_v_66 = "Version: 4.5.66" ascii
$vuln_v_67 = "Version: 4.5.67" ascii
$vuln_v_68 = "Version: 4.5.68" ascii
condition:
$pkg_name and (1 of ($vuln_v_*))
}
Remediation
Critical: Two Separate Package Upgrades Required
A single upgrade does NOT resolve all nine CVEs. The vulnerabilities span two independently versioned packages whose upgrade paths are separate. Upgrading praisonai has no effect on praisonaiagents vulnerabilities, and vice versa.
praisonai - upgrade to 4.5.97 or later
pip install "praisonai>=4.5.97"
Fixes across praisonai are cumulative across three release milestones:
| Fix Milestone | CVE Addressed | Vulnerability Class |
|---|---|---|
| 4.5.69 | CVE-2026-34935 |
MCP CLI command injection |
| 4.5.90 | CVE-2026-34934 |
Second-order SQL injection |
| 4.5.90 | CVE-2026-34936 |
SSRF via passthrough() api_base |
| 4.5.97 | CVE-2026-34952 |
WebSocket endpoints missing auth |
| 4.5.97 | CVE-2026-34953 |
OAuthManager token bypass |
| 4.5.97 | CVE-2026-34955 |
SubprocessSandbox shell=True bypass |
Installing 4.5.97 incorporates all three milestones and addresses all six praisonai CVEs. Sources: NVD; GHSA-9gm9-c8mq-vq7m (https://osv.dev/vulnerability/GHSA-9gm9-c8mq-vq7m); fix commit (https://github.com/MervinPraison/PraisonAI/commit/47bff65413beaa3c21bf633c1fae4e684348368c); PyPI release index (https://pypi.org/pypi/praisonai/json).
praisonaiagents - upgrade to 1.5.95 or later
pip install "praisonaiagents>=1.5.95"
Fixes across praisonaiagents are cumulative across two release milestones:
| Fix Milestone | CVE Addressed | Vulnerability Class |
|---|---|---|
| 1.5.90 | CVE-2026-34938 |
execute_code() sandbox bypass |
| 1.5.90 | CVE-2026-34937 |
run_python() shell=True injection |
| 1.5.95 | CVE-2026-34954 |
FileTools.download_file() SSRF |
Installing 1.5.95 incorporates both milestones and addresses all three praisonaiagents CVEs. Sources: NVD; GitLab GLAD (https://advisories.gitlab.com/pkg/pypi/praisonaiagents/CVE-2026-34954/); PyPI release index (https://pypi.org/pypi/praisonaiagents/json).
Combined upgrade command
Both packages can be upgraded in a single pip invocation. They remain independently versioned and their dependency resolution does not couple them:
pip install "praisonai>=4.5.97" "praisonaiagents>=1.5.95"
Per-CVE fix version reference
The following table provides a complete mapping for operators who need to verify a specific CVE has been addressed:
| CVE | Package | Fixed Version | Vulnerability |
|---|---|---|---|
CVE-2026-34935 |
praisonai | 4.5.69 | MCP CLI injection |
CVE-2026-34934 |
praisonai | 4.5.90 | SQL injection |
CVE-2026-34936 |
praisonai | 4.5.90 | passthrough() SSRF |
CVE-2026-34952 |
praisonai | 4.5.97 | WebSocket missing auth |
CVE-2026-34953 |
praisonai | 4.5.97 | OAuthManager token bypass |
CVE-2026-34955 |
praisonai | 4.5.97 | SubprocessSandbox bypass |
CVE-2026-34938 |
praisonaiagents | 1.5.90 | execute_code() sandbox bypass |
CVE-2026-34937 |
praisonaiagents | 1.5.90 | run_python() shell injection |
CVE-2026-34954 |
praisonaiagents | 1.5.95 | FileTools SSRF |
All fixed versions verified as present in PyPI on 2026-04-05 (https://pypi.org/pypi/praisonai/json; https://pypi.org/pypi/praisonaiagents/json).
Defence-in-Depth Mitigations
The following controls apply whilst patching is in progress or as additional hardening after patching:
-
CVE-2026-34935(MCP CLI injection): Do not permit untrusted input to influence the--mcpCLI argument. If MCP functionality is not required, disable or remove the entry point at the deployment boundary. Restrict CLI invocation to trusted operators in multi-user environments. -
CVE-2026-34938(execute_code sandbox bypass): Treatexecute_code()as an unsafe API until the patched version is deployed. Do not pass attacker-influenced strings — or Python objects derived from attacker-influenced strings — to this function. -
CVE-2026-34952andCVE-2026-34953(auth layer collapse): Until patched, restrict network access to the WebSocket (/ws) and info (/info) endpoints at the network boundary. Do not expose these endpoints to untrusted networks. -
CVE-2026-34936andCVE-2026-34954(SSRF): Apply egress filtering at the host or container level to block outbound access to169.254.0.0/16(link-local, including cloud instance metadata services) andRFC 1918private address ranges (10.0.0.0/8,172.16.0.0/12,192.168.0.0/16). This is a broadly applicable defence for any agent framework that makes outbound HTTP requests.
Indicators of Compromise
| Type | Indicator | Context |
|---|---|---|
| Process | Child process of praisonai with image bash, sh, curl, wget, nc |
CVE-2026-34935 exploitation via MCP CLI injection |
| File | /tmp/pwned containing uid output |
CVE-2026-34935 PoC indicator from GHSA-9gm9-c8mq-vq7m |
| Network | Outbound HTTP to 169.254.169.254 from a PraisonAI process |
CVE-2026-34936 or CVE-2026-34954 SSRF exploitation |
| Network | Unauthenticated WebSocket handshake to /ws |
CVE-2026-34952 reconnaissance or exploitation |
| Auth log | 200 response to a protected endpoint with a non-existent or random token value | CVE-2026-34953 OAuthManager bypass |
Strategic Context
This cluster represents the largest single disclosure event in the PraisonAI project's history to date. The concentration of findings across injection, sandbox bypass, and authentication failure categories is consistent with a codebase that had not previously undergone systematic security review (RAXE assessment). This is consistent with a broader pattern in the AI agent framework ecosystem (S2 research stream), where rapid feature development has outpaced security engineering.
The CVE-2026-34938 sandbox bypass is particularly significant for the research stream. Pattern-based block lists applied to Python string objects are a common but fragile control in AI code execution tools. The str subclass technique requires no special privileges, no memory corruption, and no knowledge of the specific block list contents — only the ability to supply a Python object. Any execute_code() implementation that relies on startswith() or similar string methods on the submitted object is vulnerable to the same class of bypass. RAXE assesses this as a technique that may appear in other agentic frameworks (RAXE assessment).
The cluster disclosure timing (2026-04-01 to 2026-04-02) coincides with increased security research activity in the AI agent framework space. RAXE will continue to monitor for follow-on disclosures against PraisonAI and related frameworks.
Intelligence Tradecraft
Analysis of Competing Hypotheses (ACH)
H1 — Coordinated internal security audit or commissioned private disclosure. Nine vulnerabilities across five CWE classes in two co-maintained packages, disclosed within the same two-day window, is more consistent with a single coordinated review than nine independent reporters. RAXE assessment: HIGH confidence.
H2 — Single external researcher with T3 (white-box) access. The GHSA advisory for CVE-2026-34935 contains precise call-chain references (cli/features/mcp.py:61, praisonaiagents/mcp/mcp.py:345, mcp/client/stdio/__init__.py:253) consistent with source code review. A single researcher with full source access could produce this breadth. RAXE assessment: MEDIUM confidence; not mutually exclusive with H1.
H3 — Opportunistic bug-bounty sweep. Less consistent with cluster density, class breadth, and coordinated disclosure timing. RAXE assessment: LOW confidence.
Key Assumptions Checklist (KAC)
- KAC-1: Fix versions are authoritative and complete. Verified against PyPI release index on 2026-04-05.
- KAC-2: The
CVE-2026-34935PoC works as described. Sourced from GHSA-9gm9-c8mq-vq7m; tested against praisonai 4.5.48 per the advisory author. RAXE has not independently retested. - KAC-3: No active exploitation has been observed. EPSS data and absence of CISA KEV listing as of 2026-04-05 are consistent with this assessment. Re-evaluate weekly.
- KAC-4: The nine CVEs constitute the complete disclosure set. Cannot be confirmed; the coordinated-review hypothesis (H1) raises the possibility of additional findings still under private embargo.
Source Grading (Admiralty Scale)
| Source | Reliability | Credibility | Grade |
|---|---|---|---|
| NVD (NIST) | A — Completely reliable | 2 — Probably true | A2 |
| GHSA-9gm9-c8mq-vq7m (GitHub / OSV) | A — Completely reliable | 1 — Confirmed by other sources | A1 |
| GitLab GLAD | B — Usually reliable | 2 — Probably true | B2 |
| FIRST.org EPSS API | A — Completely reliable | 2 — Probably true | A2 |
| PyPI release index | A — Completely reliable | 1 — Confirmed by other sources | A1 |
| Bluesky @thehackerwire.bsky.social | D — Not usually reliable | 4 — Doubtful | D4 |
The Bluesky post served as the initial signal that directed RAXE to the NVD and GHSA sources. No factual claim in this publication rests on that source alone.
Access Tier
T1 (black-box). All findings are reproducible using the distributed PyPI packages without access to source code. The GHSA advisory for CVE-2026-34935 references specific source file paths (GHSA-9gm9-c8mq-vq7m), consistent with T3 (white-box) access by the original reporter; the vulnerability is exercisable at T1 using the published PoC.
MITRE ATLAS
No specific MITRE ATLAS technique has been applied at this stage. CVE-2026-34935 and CVE-2026-34938 are relevant to agent tool execution abuse patterns within research stream S2. ATLAS mapping will be applied in a subsequent analysis pass.
References
- NVD — CVE-2026-34934 (SQL injection, CVSS 9.8): https://nvd.nist.gov/vuln/detail/CVE-2026-34934
- NVD — CVE-2026-34935 (MCP CLI injection, CVSS 9.8): https://nvd.nist.gov/vuln/detail/CVE-2026-34935
- NVD — CVE-2026-34936 (passthrough SSRF, CVSS 7.7): https://nvd.nist.gov/vuln/detail/CVE-2026-34936
- NVD — CVE-2026-34937 (run_python shell injection, CVSS 7.8): https://nvd.nist.gov/vuln/detail/CVE-2026-34937
- NVD — CVE-2026-34938 (execute_code sandbox bypass, CVSS 10.0): https://nvd.nist.gov/vuln/detail/CVE-2026-34938
- NVD — CVE-2026-34952 (WebSocket missing auth, CVSS 9.1): https://nvd.nist.gov/vuln/detail/CVE-2026-34952
- NVD — CVE-2026-34953 (OAuth token bypass, CVSS 9.1): https://nvd.nist.gov/vuln/detail/CVE-2026-34953
- NVD — CVE-2026-34954 (FileTools SSRF, CVSS 8.6): https://nvd.nist.gov/vuln/detail/CVE-2026-34954
- NVD — CVE-2026-34955 (SubprocessSandbox bypass, CVSS 8.8): https://nvd.nist.gov/vuln/detail/CVE-2026-34955
- GHSA-9gm9-c8mq-vq7m via OSV.dev (MCP CLI injection, PoC included): https://osv.dev/vulnerability/GHSA-9gm9-c8mq-vq7m
- GitHub Security Advisory GHSA-9gm9-c8mq-vq7m (MCP CLI injection, PoC included): https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-9gm9-c8mq-vq7m
- Fix commit for CVE-2026-34935 — ALLOWED_MCP_COMMANDS allowlist (v4.5.69): https://github.com/MervinPraison/PraisonAI/commit/47bff65413beaa3c21bf633c1fae4e684348368c
- GitLab GLAD — CVE-2026-34934 (GHSA-9cq8-3v94-434g): https://advisories.gitlab.com/pkg/pypi/praisonai/CVE-2026-34934/
- GitLab GLAD — CVE-2026-34936 (GHSA-x6m9-gxvr-7jpv): https://advisories.gitlab.com/pkg/pypi/praisonai/CVE-2026-34936/
- GitLab GLAD — CVE-2026-34954 (GHSA-44c2-3rw4-5gvh): https://advisories.gitlab.com/pkg/pypi/praisonaiagents/CVE-2026-34954/
- PyPI release index — praisonai: https://pypi.org/pypi/praisonai/json
- PyPI release index — praisonaiagents: https://pypi.org/pypi/praisonaiagents/json
- FIRST.org EPSS API — scores for all 9 CVEs (retrieved 2026-04-05): https://api.first.org/data/v1/epss?cve=CVE-2026-34934,CVE-2026-34935,CVE-2026-34936,CVE-2026-34937,CVE-2026-34938,CVE-2026-34952,CVE-2026-34953,CVE-2026-34954,CVE-2026-34955
- Initial signal — Bluesky post by @thehackerwire.bsky.social: https://bsky.app/profile/thehackerwire.bsky.social/post/3minam66iek2d
RAXE Labs | RAXE-2026-050 | TLP:GREEN — May be distributed without restriction