A Named Agent Framework Just Shipped Ten CVEs In One Day, And The Approval Callback Fires After The Tool Runs

September 16, 2026 · SPR{K}3 Research

On September 15, MervinPraison's PraisonAI project — an open-source multi-agent framework — got tagged with ten CVEs in a single day. Five sit at CVSS 9.8. The CVE Brief daily wrap recorded 56 critical CVEs across all vendors that day, up from 14 the day before, and the PraisonAI cluster is what drove the spike.

Individually these look like ordinary web-app bugs — missing auth on an API endpoint, an unauthenticated MCP server, an env-var default that fails open. Together they are the archetype of what breaks when you ship an agent framework, in one repo, on one day.

What the cluster actually contains

The five CVSS 9.8 items, per the VulnCheck vulnrichment and the OffSeq Threat Radar records:

Plus CVE-2026-57140 (CVSS 9.4, AgentOS GET /api/agents and POST /api/chat without auth middleware, enumerating agent names, roles, instruction prefixes, and invoking them), CVE-2026-57126 (SSRF), and CVE-2026-57132 / 57134 (auth bypass at CVSS 8.2). Fixes shipped in praisonai 4.6.58, 4.6.59, and 4.6.78, and in praisonaiagents 1.6.59.

The one that changes how you think about approvals

The most interesting item in the cluster is CVE-2026-57137, which is only CVSS 8.8 because it needs an application to be using the approval callback in the first place. It reads:

From 1.4.0 until 1.7.2, createAgentLoop() in src/praisonai-ts/src/ai/agent-loop.ts passes executable tools to generateText() before invoking the onToolCall approval callback. Because the wrapped AI SDK executes tool handlers during generation, a callback that returns false records tool_rejected only after the denied tool has already produced side effects and populated toolResults. Applications using onToolCall as a human or policy approval boundary can therefore execute rejected file, command, API, or data-modifying operations.

The approval boundary is there. It fires. It returns false. The framework records tool_rejected. And the tool has already run — the filesystem was touched, the API call was made, the data was sent. Fixed in praisonai-ts 1.7.2.

Why the whole cluster reads the same way

The five 9.8s are one shape:

The trust decision is made from something the attacker controls, at a moment when the framework cannot verify it.

An MCP server binds 0.0.0.0 and trusts anyone who reaches it. A UI endpoint takes a command and args from a caller and runs them. A jobs API takes YAML with its own approve flag inside. Auth middleware treats a missing env var as "no authentication required." An approval callback runs after the tool it was supposed to approve.

The same pattern showed up in the Rufroot MCP bridge disclosure in July, the Splunk MCP server RCE in August, the Google ADK CVSS 10.0 agent-to-agent CVE last week, and the DeepSeek Harness Host-header sandbox escape the week before. Different projects, different maintainers, same architectural mistake.

The approval callback is not a boundary if the tool has already run

The lesson from CVE-2026-57137 is worth stating in one sentence for anyone still writing agent frameworks: an approval callback that runs after the tool executes is not a boundary. It is a receipt.

By the time the callback returns, the tool call has already produced side effects. The return value can only decide what to write to a log. Every downstream system that expected onToolCall to be a policy gate is running with no gate.

This is not a subtle race. It is the ordering of two function calls in createAgentLoop. The AI SDK's generateText generates and executes tools inline. The framework wrapped it, added a callback, and named the callback onToolCall. Everyone read that as should_execute_this_tool. The semantics were this_tool_already_ran.

The runway is getting shorter

Look at the tempo. September 8: DeepSeek Harness CVE-2026-82533, CVSS 9.4, sandbox escape via Host header. September 10: Google ADK CVE-2026-79696, CVSS 10.0, agent-to-agent privilege escalation. September 11: SGLang CVE-2026-86793, unauthenticated RCE via SafeUnpickler bypass on the /update_weights_from_tensor endpoint. September 15: the PraisonAI cluster. Every week for the last four weeks, a named agent-runtime substrate has shipped a critical CVE. This week it shipped ten in one day.

The maintainers did the right thing here — shipped fixes, took CVEs. praisonai 4.6.78 and praisonaiagents 1.6.59 are out.

The industry cannot wait for the next one. Every framework in the same shape as PraisonAI — an MCP server bound to loopback with no origin check, a jobs API with a YAML-approve field inside, an onToolCall callback that runs after generateText — is one CVE assignment away from the same cluster. Runtime defense at this scale is about the shape these bugs share, not the individual bugs: an approval that arrives after the execution.


SPR{K3 is a security research operation that pairs offensive vulnerability research with runtime behavioral defense. Defend is our runtime agent. To talk about a deployment, reach us at support@sprk3.com.