Leaving the keys in the ignition of a car only three people on the block own
CVE-2026-61445 affects the AICoder UI component in PraisonAI, an open-source Python-based AI agent framework. Versions before 4.6.78 expose two LLM tool-call functions—write_to_file and execute_command—with zero path validation and zero command sanitization. The write_to_file handler uses bare os.path.join which does not reject absolute paths (os.path.join('/app', '/etc/passwd') returns /etc/passwd), enabling writes to any filesystem location. The execute_command handler passes unsanitized input straight to a shell. Because the standard Docker deployment runs as root, exploitation yields full container compromise. Affected: all versions < 4.6.78. Fixed: 4.6.78+. CWEs: CWE-22 (Path Traversal) and CWE-78 (OS Command Injection).
The vendor CVSS of 9.9 CRITICAL is technically defensible *in isolation*—Scope: Changed, low privileges, no user interaction, full CIA impact. But it overstates risk for any enterprise patching queue because PraisonAI is a niche developer tool with ~66k monthly PyPI downloads and ~9k GitHub stars, not a canonical infrastructure component. The attack surface requires authenticated access to the AICoder chat interface and relies on prompt injection as the exploitation vector—a probabilistic technique mediated by an LLM, not a deterministic HTTP request. In virtually all real deployments, PraisonAI sits on a developer laptop or an internal sandbox container that never faces the internet. The 9.9 paints this as Log4Shell-adjacent; reality is closer to a severe local-dev-tool bug that most SOCs will never encounter.
4 steps from start to impact.
Reach the AICoder chat interface
0.0.0.0:8080 inside the container; if port-forwarded or exposed via a reverse proxy, it becomes reachable. Prior to the separate fix for CVE-2026-44338, authentication was disabled by default (AUTH_ENABLED = False), which would have made this step trivial.- Network path to PraisonAI AICoder UI (typically port 8080)
- Valid session or authentication disabled (pre-CVE-2026-44338 default)
- PraisonAI is overwhelmingly deployed on developer laptops or ephemeral Docker containers, not internet-facing servers
- ~66k monthly PyPI downloads across mostly individual developers—enterprise fleet prevalence is near-zero
- Even on internal networks, a random developer's Docker container is unlikely to be reachable from other VLANs
pip list audit across hosts will surface PraisonAI. Shodan/Censys queries for PraisonAI-specific paths (/api/agents, /docs) may reveal external exposure, but expect very low hit counts.Craft a prompt-injection payload
write_to_file or execute_command tool calls with attacker-controlled arguments. This is an indirect prompt injection vector: the attacker's message is the user turn, and the LLM decides whether to honor it by calling the tool. Payload reliability depends on the LLM model, system prompt, and temperature settings. No weaponized tooling or named exploit framework is publicly available for this CVE.- Knowledge that AICoder exposes write_to_file and execute_command tools
- Ability to submit chat messages to the AICoder interface
- Prompt injection is probabilistic, not deterministic—the LLM may refuse, hallucinate, or misinterpret the payload
- No public PoC or exploit script exists as of October 2026
- Different LLM backends (GPT-4, Claude, Llama) will respond differently to the same injection, reducing reliability
Trigger arbitrary file write via path traversal
write_to_file with an absolute path like /root/.ssh/authorized_keys or /etc/crontab. The apply_llm_response handler uses os.path.join(workspace, attacker_path) which Python resolves to the absolute path when the second argument starts with /, completely bypassing the intended workspace restriction. The file is written with root permissions inside the container.- Successful prompt injection from Step 2
- Container running as root (Docker default for PraisonAI)
- If the container uses a read-only filesystem or non-root user, writes to sensitive paths will fail
- AppArmor/SELinux profiles on the host may restrict container writes to mounted volumes only
/etc/crontab, /root/.ssh/, etc.Execute arbitrary commands as root
execute_command with attacker-supplied shell commands. The function passes the string directly to the shell with no allowlist, no blocklist, and no sandboxing. The attacker achieves a root shell inside the container—reverse shells, crypto miners, data exfiltration, or lateral movement tooling can be deployed. From here, the attacker can probe the Docker socket, host mounts, and network neighbors.- Successful prompt injection from Step 2
- execute_command tool available and unsanitized
- Container network segmentation may prevent outbound connections for reverse shells
- If the Docker socket is not mounted (best practice), container-to-host escape requires a separate kernel or runtime exploit
- Blast radius is typically one container, not fleet-wide
pip install --upgrade praisonai>=4.6.78 on every host where it is installed. Version 4.6.78 adds path validation rejecting absolute paths and .. traversals in write_to_file, plus command allowlisting in execute_command. As a HIGH-severity finding, the noisgate remediation SLA is ≤ 180 days, but given this is a single pip install command, there is no reason to delay. Deploy within 30 days per the noisgate mitigation SLA.127.0.0.1 instead of 0.0.0.0. If running in Docker, do not publish the port (-p flag) or restrict it to the loopback interface (-p 127.0.0.1:8080:8080). This reduces the attack surface to local-only access, eliminating remote network exploitation. Even if prompt injection succeeds locally, the attacker must already have shell access to the host, which makes the vuln redundant.--user 1000:1000 and --read-only flags to the Docker run command. This prevents writes to sensitive paths like /etc/crontab and /root/.ssh/ even if path traversal succeeds, and limits execute_command to non-root privilege. Combined with dropping all capabilities (--cap-drop=ALL), the blast radius of successful exploitation drops dramatically./etc/, /root/.ssh/, and unexpected process execution inside PraisonAI containers. This does not prevent exploitation but provides detection and response capability, reducing dwell time. Useful as a defense-in-depth layer alongside the controls above.- WAF in front of PraisonAI — The attack payload is a natural-language prompt, not a SQL injection or XSS pattern. WAF signatures cannot distinguish a malicious AI prompt from a legitimate one without deep LLM-aware inspection, which no mainstream WAF offers today.
- Network-level IDS/IPS (Snort/Suricata) — The prompt injection travels over a normal HTTPS POST to the chat endpoint. There is no exploit signature to match; the malicious content is semantic, not syntactic.
- Pinning the LLM system prompt with safety instructions — While adding 'never write to /etc' to the system prompt may reduce success rate, prompt injection techniques routinely bypass system prompt constraints. This is not a reliable compensating control.
The supporting signals.
| In-the-wild exploitation | Not observed. Not on CISA KEV. No known campaigns targeting this CVE. GreyNoise observed scanning for PraisonAI instances within 4 hours of a *related* CVE (CVE-2026-44338, auth bypass) disclosure in May 2026, indicating attacker awareness of the project, but no exploitation telemetry for CVE-2026-61445 specifically. |
|---|---|
| Proof-of-concept availability | None public. No PoC on pocindex.io, no GitHub repos named after CVE-2026-61445, no Nuclei templates, no ExploitDB or Metasploit modules. The attack is conceptually simple (prompt injection → tool call) but no weaponized script exists. |
| EPSS score | 0.00881 (0.881% probability of exploitation in 30 days), approximately 82nd percentile. Low exploitability signal from the model. |
| CISA KEV status | Not listed. No federal mandate for remediation timelines. |
| CVSS vector analysis | CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H — The Scope: Changed flag drives the 9.9. This assumes the attacker escapes the vulnerable component's authorization scope (e.g., container → host). In practice, most Docker deployments without socket mounts do NOT grant host-level scope change, making S:C optimistic. |
| Affected versions | All PraisonAI versions < 4.6.78 (PyPI package praisonai). Current latest is 4.7.13. |
| Fixed version | 4.6.78 — adds path validation to write_to_file (rejects absolute paths and .. traversals) and command sanitization/allowlisting to execute_command. No distro backports; PraisonAI is pip-only. |
| Install base / exposure | ~1.6M total PyPI downloads, ~66k/month, ~9k GitHub stars. Developer-centric, individual-contributor adoption pattern. No evidence of significant enterprise fleet deployment. GreyNoise/Shodan exposure data for PraisonAI instances is minimal—this is not an edge appliance. |
| Disclosure date | 2026-07-11 via GitHub Security Advisory GHSA-9mp3-24cc-77mg. |
| Reporting researcher | Not publicly credited in the GHSA, NVD, or vendor advisory. Discovered via the PraisonAI project's own security advisory process. |
Sources.
Why this verdict
- Minuscule enterprise footprint: PraisonAI has ~66k monthly PyPI downloads, overwhelmingly individual developers and researchers. An enterprise fleet of 10,000 hosts is statistically unlikely to have *any* PraisonAI installations. The vendor CVSS of 9.9 treats this as ubiquitous infrastructure; it is not.
- Prompt injection is a probabilistic attack vector: Unlike a crafted HTTP request that deterministically triggers a buffer overflow, prompt injection depends on the LLM model, system prompt, temperature, and alignment guardrails. Exploitation reliability is significantly lower than a traditional RCE, warranting AC:H-equivalent friction even though the CVSS formally marks AC:L.
- Blast radius capped at one container/host: Even successful exploitation yields root inside a single Docker container. Without a mounted Docker socket or kernel exploit, there is no lateral movement to the host or fleet. This is not a domain controller, hypervisor, or CI/CD server—it is a developer sandbox.
- No PoC, no KEV, low EPSS: Zero public exploit code, not on CISA KEV, EPSS at 0.881%. The threat intelligence signal is uniformly cold.
- Role multiplier: (a) *Developer workstation/sandbox* (>95% of installs): chain succeeds, blast radius = one container. Severity remains HIGH for that host but does not propagate. (b) *Internal AI automation server* (<5%): chain succeeds if chat UI is reachable on internal network, blast radius = one server, possible data on that host. (c) *CI/CD pipeline integration* (<1% of installs): theoretically possible if AICoder is embedded in a build workflow, which would elevate blast radius to supply-chain. However, PraisonAI is NOT a canonical CI/CD component—it is an AI agent framework. No evidence of CI/CD adoption pattern. This role does not meet the ≥1% threshold to set a floor.
- Attacker interest exists for PraisonAI broadly: GreyNoise documented scanning for PraisonAI endpoints within 4 hours of a related CVE disclosure (CVE-2026-44338). While that was a different bug, it confirms adversary awareness of the project—preventing a full downgrade to MEDIUM.
Why not higher?
A CRITICAL rating would require either a canonical high-value deployment role (this is a developer tool, not a DC/hypervisor/CI server) or evidence of active exploitation (none exists). The probabilistic nature of prompt injection, the near-zero enterprise footprint, and the container-scoped blast radius all argue against CRITICAL. The 9.9 vendor score is a theoretical maximum that doesn't reflect how this software actually lives in production environments.
Why not lower?
Root-level RCE is root-level RCE, even in a container. The technical exploit chain is short (two steps from chat access to shell), the fix was only released three months ago so many pip installs may still be vulnerable, and GreyNoise data shows real attacker interest in PraisonAI as a target class. Any developer running an unpatched instance with the AICoder UI exposed—even on an internal network—faces genuine compromise risk. MEDIUM would understate the severity for the (small) population actually running this tool.
Crowdsourced verification payload.
Run this script on any host where PraisonAI might be installed. Requires no special privileges—just the ability to run python3. Invoke with: python3 check_cve_2026_61445.py. The script checks the installed praisonai package version and reports VULNERABLE, PATCHED, or UNKNOWN.
#!/usr/bin/env python3
"""Check for CVE-2026-61445: PraisonAI AICoder arbitrary file write + RCE.
Fixed in version 4.6.78.
Exit codes: 1 = VULNERABLE, 0 = PATCHED, 2 = UNKNOWN
"""
import sys
try:
from importlib.metadata import version as get_version, PackageNotFoundError
except ImportError:
from importlib_metadata import version as get_version, PackageNotFoundError
FIXED_VERSION = (4, 6, 78)
def parse_version(v):
"""Parse a PEP-440 version string into a comparable tuple."""
parts = []
for segment in v.split('.'):
# strip pre/post/dev suffixes for comparison
num = ''.join(c for c in segment if c.isdigit())
if num:
parts.append(int(num))
return tuple(parts)
try:
installed = get_version('praisonai')
except PackageNotFoundError:
print('UNKNOWN — praisonai package is not installed on this host.')
sys.exit(2)
parsed = parse_version(installed)
if not parsed:
print(f'UNKNOWN — could not parse version string: {installed}')
sys.exit(2)
if parsed < FIXED_VERSION:
print(f'VULNERABLE — praisonai {installed} is installed (fixed in 4.6.78).')
sys.exit(1)
else:
print(f'PATCHED — praisonai {installed} is installed (>= 4.6.78).')
sys.exit(0)