PraisonAI: 24 Advisories in 33 Hours Point at a Fixed Version That Was Never Published to PyPI

Between 7 October 2026 at 14:06 UTC and 8 October 2026 at 22:00 UTC — a window of roughly 33 hours — 24 GitHub security advisories covering 25 distinct CVE identifiers were published against the PraisonAI agent framework. Fifteen name the praisonai PyPI distribution; nine name praisonaiagents. By GitHub's own severity labels the batch breaks down as 3 critical, 14 high, and 7 moderate.

This is the fourth large PraisonAI wave we have covered in 2026, after the April cluster, the May workspace IDORs, and the September 27-CVE batch. The volume alone is no longer the story. What makes this batch worth a separate briefing is a remediation defect that sits underneath all 24 records at once.

Every advisory prescribes a version pip cannot install

All fifteen praisonai advisories declare the same fixed version: 4.6.78. All nine praisonaiagents advisories declare 1.6.78. We checked both against the registries that actually serve the packages.

praisonaiagents 1.6.78 exists — it was uploaded to PyPI on 25 June 2026. That half of the batch is actionable as written.

praisonai 4.6.78 does not exist on PyPI. We enumerated every file in the PyPI simple index for praisonai — 1,656 distinct versions, zero of them yanked — and the sequence runs 4.6.77 → 4.6.81. Versions 4.6.78, 4.6.79 and 4.6.80 are absent entirely. On GitHub, by contrast, all three exist: v4.6.78 is a real tag at commit 393de394, dated 25 June 2026 at 08:21 UTC, with a published (non-draft) release object attached. The code was tagged and released on GitHub; the artifact was never pushed to the index that pip install praisonai reads.

The practical consequence is narrow but sharp. A defender who does exactly what fifteen advisories instruct — pin or upgrade to praisonai==4.6.78 — gets a resolution failure, not a patched install. Automated dependency tooling that consumes the GitHub Advisory Database or OSV will compute a remediation target that cannot be satisfied from the default index. There is no yank, no deprecation marker, and no advisory erratum explaining the gap; the record simply names a version the ecosystem cannot serve.

The fixes themselves did ship — in a later version

This is a metadata failure, not an unpatched-software story, and the distinction matters. We verified the code state directly at the relevant tags rather than trusting the advisory text.

Take CVE-2026-61444 (also carrying the duplicate identifier CVE-2026-62176, GHSA-g6j7-pffp-8whg, critical, CWE-94), which reports code injection in the deploy API generator. The advisory describes src/praisonai/praisonai/deploy/api.py interpolating an unsanitised agents_file into an f-string that is written to disk and run through subprocess.Popen(). Reading the file at each tag:

  • v4.6.77 — contains the raw agent_file="{agents_file}" interpolation. Vulnerable, matching the advisory.
  • v4.6.78 — raw interpolation gone, replaced by a pre-escaped {safe_agents_file} substitution. Fixed.
  • v4.6.81 and v4.6.83 — both carry the safe_agents_file form.

So the first installable version carrying this fix is 4.6.81 (PyPI, 27 June 2026), not the 4.6.78 the advisory names. For this specific CVE, upgrading to 4.6.81 or later resolves it. We did not re-verify the code state for all fifteen praisonai advisories individually, so defenders should treat 4.6.81 as the minimum credible floor rather than a blanket all-clear — and note that the current release is 4.7.13 (7 October 2026), far ahead of either.

One finding in the batch is not fixed by any upgrade

CVE-2026-60085 (GHSA-5r6c-gj4g-r697, high, CWE-273) is the one defenders should read closely, because it describes a control that does not exist rather than a control that can be bypassed. The advisory states that SecurityPolicy in praisonaiagents/sandbox/config.py declares fields — allow_subprocess, allowed_paths, blocked_paths, allowed_commands, blocked_commands, allowed_imports, blocked_imports — and that its strict() constructor is documented as producing "a strict security policy for untrusted code," while the default subprocess backend consults none of them.

We tested that claim against the current tag, v4.7.13, by reading every non-test Python file under the sandbox trees. The result is consistent with the advisory: those field names appear in config.py, the data class that declares them, and in no other non-test sandbox module. manager.py, protocols.py, security.py, _sandbox_bridge.py and the praisonai-side sandbox registry reference none of them. A policy object whose restrictions are declared but never read by the enforcement path is configuration theatre: code that calls SecurityPolicy.strict() and proceeds to execute untrusted model output is relying on a guarantee the runtime does not implement.

We are reporting a string-level absence across the sandbox modules at one tag, not a runtime exploitation result. We did not execute the framework. The advisory's authors state they confirmed the behaviour at runtime — subprocess.run(['id']) succeeding as root under a strict() policy with allow_subprocess=False — and that claim is theirs, not ours. Our independent contribution is that the pattern still holds on the latest tag, two days after disclosure.

The rest of the batch, in shape

The remaining findings cluster into recognisable agent-framework failure modes rather than novel attack classes:

  • Default-off authentication. CVE-2026-61427 (MCP HTTP-stream transport unauthenticated because the CLI defaults --api-key to None, exposing initialize and tools/list), CVE-2026-60091 (Jobs API adds auth middleware only when an env var is set), and CVE-2026-61435 (a Host: 127.0.0.1 header defeats a localhost-only auth guard — notably, a bypass of an earlier patch for the same surface).
  • Unsigned webhooks. CVE-2026-61428 and CVE-2026-61436 both target AgentMail webhook mode binding 0.0.0.0 and processing message.received events with no signature verification, letting any network peer inject spoofed-sender messages into an agent session. The first advisory notes sibling bots fail closed when no secret is configured; AgentMail omits the check.
  • Allowlist bypass. CVE-2026-61434 escapes a shell-command allowlist through find's built-in -exec action — no shell metacharacters required, because find itself performs the execution and the + batch terminator substitutes for the blocked ;. This defeats hardening added for two earlier advisories.
  • Workspace escape into prompts. CVE-2026-60088 and CVE-2026-61431 both let repository-controlled files (.praisonai/commands/*.md, .praisoncontext) name absolute or .. paths, pulling process-readable files outside the workspace into the model prompt — an exfiltration channel that ends at whichever provider receives the request.
  • Prompt-injection defence that logs instead of blocking. CVE-2026-61439 reports that the block threshold defaults to CRITICAL, reached only when three or more detector categories fire at once, so a single-vector instruction-override match produces a HIGH result that is written to the warning log and forwarded to the model unchanged.
  • Critical LLM-to-shell paths. CVE-2026-61445 and CVE-2026-61447 describe agent components handing LLM-chosen file paths and commands to open() and create_subprocess_exec() with no validation, in containers running as root.

Three of these — the find -exec bypass, the Host-header bypass, and the threshold-misconfigured injection defence — are failures of controls that were themselves added as security fixes. That is the more durable lesson in this batch: in agent frameworks, the allowlist, the localhost check and the injection scanner are attack surface in their own right, and each needs the same adversarial review as the code they were written to protect.

What to do

  • Do not pin to praisonai==4.6.78. It is not installable from PyPI. If your remediation ticket or SCA tool produced that target from the advisory feed, it will fail to resolve. Move to the current release (4.7.13 at time of writing) rather than chasing the version the advisories name.
  • praisonaiagents==1.6.78 is real and installable (PyPI, 25 June 2026), but it is fifteen releases behind the current 1.7.11. Upgrade forward, not to the advisory floor.
  • Do not rely on SecurityPolicy to contain untrusted code. On the current tag its command, path and import restrictions appear in the declaring data class and nowhere in the enforcement modules. If you are executing model-generated code, put a real boundary around it — a container with a dropped capability set, a seccomp profile, a separate uid — and treat the framework's policy object as documentation of intent only.
  • Audit the default-off switches before exposure, not after. Three advisories in this batch reduce to "authentication is applied only when an optional variable is set." Grep your deployment for PRAISONAI_JOBS_API_KEY, the MCP --api-key flag, and PRAISONAI_CALL_AUTH, and confirm each is set rather than assuming the default is safe.
  • Check whether your dependency scanner silently dropped these. An advisory whose fixed version cannot be resolved may be reported as unfixable, deprioritised, or skipped depending on the tool. Verify that 24 records actually appear in your queue.

Verification note: the 24 advisories, their GHSA and CVE identifiers, publication timestamps, GitHub severity labels, CWE assignments and declared fixed versions were read by us directly from the OSV API, which mirrors the GitHub Advisory Database. The absence of praisonai 4.6.78 was confirmed against the PyPI JSON API and independently against the PyPI simple index (1,656 versions, no yanked files); the presence of praisonaiagents 1.6.78 was confirmed the same way. The existence of the v4.6.78 git tag, its commit SHA and date, and its non-draft release object were read from the GitHub API. The deploy/api.py before/after code state at v4.6.77, v4.6.78, v4.6.81 and v4.6.83, and the sandbox-module field survey at v4.7.13, are our own source inspections via the GitHub contents API on 9 October 2026. We did not execute PraisonAI; no runtime exploitation claim in any advisory was independently reproduced, and the CVE-2026-60085 runtime results described above are the reporting researcher's, explicitly attributed. Duplicate-identifier status for CVE-2026-62176 is as recorded in the advisory aliases.

Sources: