Most vulnerability disclosures end with a patch. This one ends with a disagreement. On April 15, 2026, OX Security published an advisory describing command injection through the STDIO transport used by Anthropic's Model Context Protocol SDKs — a default behavior that propagated into every official language binding (Python, TypeScript, Java, Rust) and from there into thousands of downstream projects. By OX's count the issue touches more than 7,000 publicly accessible servers and packages totaling more than 150 million downloads, with as many as 200,000 instances affected in aggregate.
The twist is Anthropic's response. Rather than patching, Anthropic confirmed the behavior is by design: the STDIO execution model is, in their framing, a "secure default," and sanitizing the inputs that flow between an MCP configuration and the process spawn is the developer's responsibility. That makes this a by-design vulnerability — vendor-acknowledged, security-impacting, and explicitly not going to be fixed upstream. The disclosure carried a cluster of downstream CVEs in products that inherited the behavior without adding their own sanitization, and the debate over who owns the fix carried into May 2026 across CSA research notes and security press.
Whether you call it a vulnerability or a sharp edge, the operational consequence is identical: if you run MCP servers that use STDIO transport, the safety of every command spawn is on you, not on the SDK. This post explains the mechanics, the downstream CVEs, the detection signals, and why "sanitization is the developer's responsibility" is a load-bearing sentence for anyone deploying agents in 2026.
TL;DR
- OX Security disclosed (April 15, 2026) command injection through the MCP STDIO transport in Anthropic's official SDKs — Python, TypeScript, Java, Rust — affecting 7,000+ public servers, 150M+ downloads, up to ~200,000 instances.
- The SDKs spawn local processes from MCP configuration without sanitizing the command/argument inputs. Untrusted configuration or prompt-injected config changes can inject OS commands.
- OX identified four attack variants: direct UI config injection, allowlist/hardening bypass via command flags (e.g.,
npx -c <command>), prompt-injection-driven config modification, and hidden STDIO processing reachable over the network even when no UI exposes it. - Downstream CVEs include CVE-2026-30623 (LiteLLM), CVE-2026-30624 (Agent Zero), CVE-2026-30625 (Upsonic), CVE-2026-40933 (Flowise), CVE-2026-30615 (Windsurf), CVE-2026-26015 (DocsGPT), and CVE-2025-65720 (GPT Researcher), among others.
- Anthropic declined to patch, calling STDIO a secure default and sanitization a developer responsibility. Several vendors (LangChain, Amazon/awslabs, NVIDIA, and IDE makers) likewise declined, citing design intent. Others patched (LiteLLM fixed in v1.83.6+).
- Monday morning: patch the downstream products that did fix, sanitize/allowlist STDIO spawns yourself, prefer non-STDIO transports where possible, and lock down who can write MCP config.
What happened
OX Security researchers Moshe Siman Tov Bustan, Mustafa Naamnih, and Nir Zadok published "MCP STDIO Command Injection" on April 15, 2026. The core finding: the official MCP SDKs, when using the STDIO transport for local tool execution, take command and argument inputs from MCP configuration and pass them to a process spawn without sanitizing them. Because the behavior originates in Anthropic's SDK and is inherited by every binding, the same weakness recurs across the ecosystem — what OX framed as a systemic supply-chain issue rather than a single-product bug.
The advisory enumerated affected downstream products with CVEs:
| CVE | Product | Status note | |-----|---------|-------------| | CVE-2026-30623 | LiteLLM | Fixed in v1.83.6+ | | CVE-2026-30624 | Agent Zero (0.9.8) | | | CVE-2026-30625 | Upsonic (0.71.6) | | | CVE-2026-40933 | Flowise (>3.1.0) | | | CVE-2026-30615 | Windsurf (1.9544.26) | | | CVE-2026-26015 | DocsGPT (0.15.0) | | | CVE-2025-65720 | GPT Researcher (3.3.7–3.4.4) | |
OX also noted unassigned cases (LangFlow, LangBot, and undisclosed products), and that independent researchers had filed related STDIO-injection CVEs (CVE-2025-49596, CVE-2026-22252, CVE-2026-22688, CVE-2025-54994, CVE-2025-54136). Crucially, several upstream parties — Anthropic for the transport layer, plus LangChain, Amazon/awslabs, NVIDIA, and IDE vendors (Gemini-CLI, Claude Code, GitHub Copilot, Cursor) — declined to patch, citing design intent or developer liability. The Cloud Security Alliance issued research notes on the disclosure ("MCP by Design: RCE Across the AI Agent Ecosystem"), keeping the debate active into May 2026.
How the attack works
STDIO transport means an MCP client launches a local MCP server as a child process and talks to it over standard input/output. The configuration specifies the command and arguments to run — for example, npx some-mcp-server. The vulnerability is that the path from "configuration string" to "spawned process" does not enforce sanitization, so whoever controls the configuration controls what executes. OX described four variants:
1. Direct UI exploitation. Products that expose an MCP-adapter configuration screen let a user paste a malicious JSON config. The command/args land in the spawn unsanitized, so the config is the payload.
2. Hardening bypass via command flags. Even products that added an allowlist of permitted commands can be defeated by abusing flags of the allowlisted command. The canonical example: npx is allowlisted, but npx -c "<arbitrary shell>" runs an arbitrary command through the permitted binary. The allowlist checked the program name, not what the program would do.
3. Prompt-injection-driven config modification. This is the agentic variant. Attacker-controlled content the agent processes (a document, an issue, a webpage) instructs the agent to modify the MCP configuration — adding or rewriting a STDIO server entry — without explicit user consent. The agent edits its own toolset, and the next spawn runs attacker-chosen commands.
4. Hidden STDIO processing reachable over the network. Some products process STDIO config server-side even when no UI option exposes it. A network request can reach that backend logic and inject a command, with nothing in the interface hinting the capability exists.
// Illustrative MCP STDIO config showing the allowlist-bypass shape.
// NOT functional exploit code. The product allowlisted "npx"; the flag carries the payload.
{
"mcpServers": {
"innocuous-name": {
"command": "npx",
"args": ["-c", "<arbitrary command runs here despite the allowlist>"]
}
}
}
The through-line across all four: the trust boundary sits at "who can write MCP config," and the SDK assumes that boundary is the developer's to enforce. Where a product let untrusted input (a UI field, a network request, or a prompt-injected instruction) reach the config, the boundary collapsed.
Detection
- Process-spawn lineage from MCP clients. Monitor child processes spawned by MCP host processes and agents. A spawn whose command line contains shell metacharacters,
-c/-e/--eval-style flags, pipes, or nested interpreters (bash -c,sh -c,node -e,python -c) is the high-fidelity signal. - MCP config writes from untrusted paths. Alert on modifications to MCP configuration files or settings that originate from network requests, UI submissions, or agent actions rather than a known developer/change process. Config change plus immediate new-process spawn is the injection sequence.
- Allowlist-defeating flags. If you allowlist commands, specifically watch for allowlisted binaries invoked with code-execution flags (
npx -c,npm exec, etc.). The allowlist log alone will look clean; the flags are where the bypass hides. - Egress from freshly spawned MCP children. A newly spawned STDIO server immediately making outbound network connections or reading credential files is consistent with an injected payload rather than normal tool startup.
- Inventory STDIO usage. Enumerate which of your MCP deployments use STDIO transport and which downstream products (LiteLLM, Flowise, Windsurf, DocsGPT, etc.) you run, mapped against the CVE list. You cannot detect what you have not inventoried.
What to do Monday morning
- Patch the downstream products that fixed it. Where a maintainer shipped a fix, take it. LiteLLM is fixed in v1.83.6+. Check Agent Zero, Upsonic, Flowise, Windsurf, DocsGPT, and GPT Researcher against their advisories and upgrade.
- Assume the SDK won't sanitize for you. For products that declined to patch, and for any MCP server you build, add your own sanitization and strict allowlisting at the config-to-spawn boundary — and validate flags, not just program names, so
npx -ccannot slip through. - Prefer non-STDIO transports where you can. Where an MCP server can run over a network transport with proper authentication instead of local STDIO spawn, that removes the local-command-injection surface entirely. Evaluate per deployment.
- Lock down who can write MCP config. Treat MCP configuration as privileged. Restrict UI fields and APIs that accept config, and ensure agents cannot rewrite their own STDIO server entries from untrusted input. This kills variants 1, 3, and 4.
- Hunt for prior injection. Review MCP config history and process-spawn logs for shell metacharacters and allowlist-bypass flags predating your fixes.
- Inventory your MCP STDIO surface and keep it current, mapping deployments to the disclosed CVEs so the next downstream advisory is a lookup, not a fire drill.
Why this keeps happening
This disclosure crystallizes a problem the supply-chain world knows well, now reproduced in the AI tooling layer: a default in a widely depended-upon component propagates its risk to everyone downstream, and the fix is socially contested rather than technically hard. The SDK ships a behavior; thousands of projects adopt it verbatim; each one inherits the sharp edge. When the upstream maintainer declines to change the default — here, framing STDIO as a "secure default" with sanitization delegated to developers — the burden fragments across every downstream project, most of which never realized they had inherited a responsibility.
Reasonable engineers can disagree on whether spawning processes from configuration is a vulnerability or a documented capability. But that disagreement is itself the risk. A by-design behavior that is "vendor-acknowledged, security-impacting, and not going to be fixed upstream" is the worst kind of dependency, because no patch will ever arrive to close it and many downstream maintainers will reach the same "developer's responsibility" conclusion the SDK did. The result is a long tail of products where the sanitization step that should exist simply doesn't, and the only signal that you are exposed is an advisory naming your specific dependency.
The structural fix
When the upstream will not patch, your leverage is inventory, scoping, and runtime control. You need to know which MCP servers you run, which use STDIO transport, and what each is permitted to execute — that is the role of MCP server governance and MCP server security: an inventory of MCP servers and their declared capabilities, so an unsanitized STDIO spawn surface is a tracked finding rather than an unknown. Capability scoping limits what a spawned tool can do even if injection succeeds, and defending the prompt-injection variant — where an agent rewrites its own config from untrusted content — ties directly to prompt-injection defense. None of this overrides a vendor's by-design decision, but it shortens the distance between "a dependency inherited an unsanitized spawn" and "we found and contained it" — which, for a vulnerability class that will never be patched upstream, is the whole game.
What we know we don't know
- In-the-wild exploitation breadth. OX documented attack variants and named CVEs; the extent of real-world exploitation across the 7,000+ servers and 150M+ downloads was not quantified at disclosure. Treat the figures as exposure surface, not confirmed compromise.
- Which "undisclosed products" are affected. OX referenced undisclosed and unassigned cases (LangFlow, LangBot, others). You may run an affected product that is not yet named — hence the emphasis on sanitizing your own spawn boundary regardless.
- Whether the upstream position will hold. Anthropic and several vendors framed this as by-design as of April–May 2026. Whether ecosystem pressure or a future spec revision changes that default is unresolved. Do not plan around an upstream fix arriving.
- Vulnerability-versus-feature framing. Some parties dispute that this is a vulnerability at all. This analysis treats it as exploitable-by-default behavior you must defend against; reasonable parties disagree on labeling.
References
- OX Security — MCP STDIO Command Injection: Full Vulnerability Advisory (April 15, 2026): https://www.ox.security/blog/mcp-supply-chain-advisory-rce-vulnerabilities-across-the-ai-ecosystem/
- OX Security — The Mother of All AI Supply Chains: Critical, Systemic Vulnerability at the Core of MCP: https://www.ox.security/blog/the-mother-of-all-ai-supply-chains-critical-systemic-vulnerability-at-the-core-of-the-mcp/
- VentureBeat — 200,000 MCP servers expose a command-execution flaw that Anthropic calls a feature: https://venturebeat.com/security/mcp-stdio-flaw-200000-ai-agent-servers-exposed-ox-security-audit
- The Hacker News — Anthropic MCP Design Vulnerability Enables RCE, Threatening AI Supply Chain: https://thehackernews.com/2026/04/anthropic-mcp-design-vulnerability.html
- LiteLLM — Security Update: CVE-2026-30623 Command Injection via Anthropic's MCP SDK: https://docs.litellm.ai/blog/mcp-stdio-command-injection-april-2026
- Cloud Security Alliance — MCP by Design: RCE Across the AI Agent Ecosystem (research note): https://labs.cloudsecurityalliance.org/research/csa-research-note-mcp-by-design-rce-ox-security-20260420-csa/
- Infosecurity Magazine — Systemic Flaw in MCP Protocol Could Expose 150 Million Downloads: https://www.infosecurity-magazine.com/news/systemic-flaw-mcp-expose-150/
Internal Safeguard resources: