Breachwire.riscent

Breach report

The MCP server RCE pattern: when an AI's tool runs your words through a shell

AI & LLM BreachesCritical (RCE)CVE-2025-53107, CVE-2025-53967, CVE-2025-59834, CVE-2025-692562025-08
The bottom lineA recurring flaw across the Model Context Protocol ecosystem: an MCP server passes an LLM-filled parameter to a shell without sanitization, so indirect prompt injection becomes remote code execution.
Category
AI & LLM Breaches
Type
Vulnerability class · Multiple CVEs
Date
2025-08
Severity
Critical (RCE)
OWASP
LLM05 Improper Output Handling; LLM01 Prompt Injection
CWE / CVE
CWE-78 CVE-2025-53107, CVE-2025-53967, CVE-2025-59834, CVE-2025-69256

What happened

The Model Context Protocol (MCP) is the standard that lets AI agents call external tools. Through 2025 a repeating vulnerability appeared across popular MCP servers: a server takes a parameter the language model fills in and passes it to a shell — typically Node's child_process.execwithout sanitizing it. Because an attacker can influence what the model produces through indirect prompt injection, they can smuggle shell metacharacters into that parameter and make the server run arbitrary commands on the host.

The pattern was confirmed in multiple widely used servers, each with its own CVE: the Git MCP server (CVE-2025-53107), a Figma developer MCP server (CVE-2025-53967), an Android Debug Bridge MCP server (CVE-2025-59834), and a Serverless Framework MCP server (CVE-2025-69256), among others. It is not one bug — it is a systemic design mistake replicated across the ecosystem.

Root cause

Model and tool output was treated as trusted input to a shell. The server authors assumed the argument was benign because "the AI generated it," but the AI's output is attacker-influenceable. Stripped of the AI framing, this is classic OS command injection (CWE-78) — OWASP LLM05 Improper Output Handling, triggered by LLM01 Prompt Injection.

How it would have been caught

Static analysis rules (Semgrep, CodeQL) that flag child_process.exec, os.system, eval, or shell calls on tool-parameter data would have caught the pattern at the source. Software Composition Analysis catches the specific CVEs in dependencies. The reproduction is a single call to the tool with an argument such as ; id or $(...), asserting the injected command does not run.

How to prevent it

  • Never pass model or tool data to a shell. Use argument-array APIs (execFile, spawn without a shell) or a strict allowlist with escaping.
  • Run tool execution under a least-privilege, egress-jailed sandbox so even a successful injection cannot reach the network or protected files.
  • Screen tool inputs with an injection classifier and keep untrusted content boxed.

The Breachwire test (red → green)

Call the tool with a metacharacter payload and confirm the injected command executes (the vector is real). Switch to a no-shell argument array and sandbox the execution, then confirm the same payload is treated as a literal argument and does nothing, while a legitimate tool call still succeeds.