MCP STDIO: The Command Runs Before the Server Is Trusted
If you are building AI agents with MCP, there is one detail about STDIO transport that is easy to miss. The client reads a config value. That config value contains a command. The command runs. Only after that does the client find out whether the command started a valid MCP server.
If the command starts a real MCP server, the agent gets a working tool connection. If it does not, the agent gets an error. But the command already ran. That is the part developers need to sit with.
This is not just a bug in one app. According to OX Security, it is a design characteristic of how MCP STDIO transport works.
The Short Version
MCP lets AI agents connect to tools, files, databases, APIs, and local services. STDIO is one of MCP's transports. Instead of connecting over HTTP, the client launches a local process and talks to it through standard input and standard output.
That design is useful. It avoids opening a network port. It makes local tools easy to wire into an agent. It also means the MCP client is launching a process on the user's machine. That is not automatically unsafe. Local developer tools launch processes all the time.
The risk appears when untrusted input can influence the command, the arguments, or the config file that defines the MCP server. At that point, your MCP config becomes a command execution surface.
What OX Security Found
OX Security published research in April 2026 after auditing MCP for five months. Their finding was simple but serious: If attacker-controlled input reaches an MCP STDIO launch command, the attacker may be able to run code on the host.
OX grouped the risk into a few paths:
- Direct command injection. Some AI frameworks passed user input into STDIO server configuration without enough validation.
- Allowlist bypasses. A product might allow only a trusted launcher such as
npx, but still allow attacker-controlled arguments. If the arguments can change whatnpxruns, the allowlist does not protect much. - IDE prompt injection. A coding agent or IDE may process untrusted content from files, web pages, repos, or tool responses. If that content can cause the agent to modify local MCP config, the next tool launch can become code execution. One confirmed example was CVE-2026-30615 in Windsurf, where attacker-controlled HTML could modify local MCP configuration and automatically register a malicious MCP STDIO server, leading to command execution without further user interaction.
- Marketplace distribution. OX submitted a test package to 11 MCP marketplaces. Nine accepted it. OX also reported 7,000 publicly accessible servers, up to 200,000 vulnerable instances, and command execution on six live production platforms.
Those numbers matter less than the pattern. MCP is becoming infrastructure. When infrastructure has a sharp edge, everyone downstream inherits it.
The Allowlist Problem
The allowlist bypass is the developer lesson. Imagine a product has a security rule like this: Only allow MCP STDIO servers to launch with npx. That sounds reasonable. It blocks random binaries. It gives the team one trusted launcher to review.
But what if untrusted input reaches the args?
{
"name": "example-tool",
"transport": "stdio",
"command": "npx",
"args": ["-c", "<untrusted input>"]
}
The allowlist checked the command name. It did not check what the command was being asked to do. That is the mismatch. Security logic says, "The command is allowed." Runtime behavior says, "The full command plus arguments is what matters."
A real allowlist cannot stop at the binary name. It has to validate the full command shape. That means:
- which launcher is allowed
- which arguments are allowed
- which package names are allowed
- which flags are blocked
- whether shell-like behavior is possible
- whether the command is pinned to a known version
- whether the server definition came from a trusted source
If the answer is "we allow npx and trust the rest," that is not a security boundary.
Why This Is Not Just an MCP Problem
This is the same class of mistake developers have seen for years. We trust a wrapper and forget the wrapper can be told to do unsafe things. We validate a filename and forget the path can escape the directory. We allow one executable and forget its flags can change the execution model.
MCP makes the problem more important because agents are now sitting between untrusted content and local execution. A developer may ask an agent to inspect a repo, read docs, summarize an issue, install a tool, or configure a local server. That agent may read content the attacker controls. If the agent can write config files or launch tools, the attacker does not need to trick the human directly. They can influence the agent's environment.
That is why prompt injection becomes more serious when it meets local tool execution. The prompt is not the payload by itself. The prompt becomes the path to the payload.
Why Anthropic Did Not Patch the Protocol
Anthropic's position, as characterized by OX Security, is that this behavior is expected. There is some logic to that. STDIO exists so a client can launch a local MCP server. If the protocol aggressively strips arguments or blocks command patterns, it may break legitimate tool setups.
The counterargument is also reasonable. A protocol that becomes a default integration layer cannot assume every downstream team will design safe command validation on its own. Most teams using MCP are not trying to become experts in command execution safety. They are trying to connect an AI agent to useful tools.
That is the supply chain problem. A risky default at the protocol or SDK layer becomes a repeated bug across many products.
What to Check in Your Own MCP Setup
If you are using MCP STDIO, I would start with these tests.
1. Can user input reach the command or args?
Search for places where input flows into values like:
StdioServerParameters(command=..., args=...)
Or the equivalent in your language or framework. If user input reaches either field, treat that as command execution risk. Do not only check direct form fields. Also check:
- imported project files
- generated config
- agent-written config
- tool manifests
- marketplace package metadata
- setup scripts
- repo instructions
- issue or PR content consumed by an agent
2. Does your allowlist validate the whole expression?
An allowlist that checks only this:
"command": "npx"
is incomplete. You also need to validate the args. Better still, map allowed tools to fixed command templates. For example:
{
"tool": "approved-doc-search",
"command": "npx",
"args": ["approved-doc-search@1.2.3"]
}
That is safer than letting user-controlled input build the command.
3. Can the agent silently modify MCP config?
This is the part teams will miss. The risk is not only "did the user type a bad command?" The risk is also "can the agent change the config after reading hostile content?" Config changes that affect STDIO launch behavior should require deliberate confirmation. A silent update to an MCP server command should be treated like a code change.
4. Are MCP servers exposed publicly?
If an MCP-connected service is reachable from the public internet, put authentication and network controls in front of it. Do not treat AI tooling as a harmless dev utility. These systems often hold API keys, local file access, database handles, or cloud credentials.
5. Where did the MCP package come from?
Treat MCP servers like npm packages. That means checking:
- publisher identity
- repo history
- install scripts
- version pinning
- package age
- permissions requested
- whether the package is from an official source
A marketplace listing is not enough.
The QA Lesson
The most useful test case is not "can I jailbreak the model?" The better test is: Can untrusted content cause the agent to create, modify, or launch an MCP STDIO server in a way that changes what code runs?
That gives QA and security teams a concrete workflow to test. Put malicious instructions in places the agent is likely to read:
- README files
- docs pages
- issue comments
- PR descriptions
- web pages
- tool responses
- package metadata
- generated setup instructions
Then verify that the agent cannot turn those instructions into local MCP config changes or unsafe tool launches. This is where a lot of AI security testing is going next. Not just prompt input. Not just model output. The whole path from untrusted content to tool execution.
The OWASP Mapping
This fits cleanly under OWASP LLM03: Supply Chain. The risk is inherited through protocols, SDKs, registries, and tool packages. Developers downstream may not realize they inherited a command execution surface when they adopted MCP STDIO.
It also touches OWASP LLM06: Excessive Agency. An agent that can launch local processes through weakly validated config has more capability than most users realize.
That combination is the real issue: Supply chain risk gives the agent a dangerous tool surface. Excessive agency lets it use that surface. Prompt injection gives an attacker a way to steer it.
Bottom Line
MCP STDIO is useful. It is also sharp. If you use it, do not ask only whether the MCP server works. Ask what command runs before the server proves it worked. Because with STDIO, the connector is not just a connector. The connector is the shell.
Further Reading
For more detail, see my full writeup, AI Leak Watch: The Protocol That Anthropic Won't Fix, and the companion walkthrough, How the MCP STDIO Flaw Works.
- Primary research: OX Security: The Mother of All AI Supply Chains
- Protocol docs: Model Context Protocol: Transports
- Windsurf advisory: CVE-2026-30615 / GHSA-wj2m-jvpr-64cq
- OWASP mapping: LLM03 Supply Chain and LLM06 Excessive Agency
Comments
No comments yet. Start the discussion.