LetterMCP

MCP Agent Sandbox Escape Vulnerability Patterns

MCP servers lack built-in security, leaving agents vulnerable to sandbox escapes.

· 9 min read · Updated
Cover illustration for “MCP Agent Sandbox Escape Vulnerability Patterns”
Agent Security · September 18, 2026 · 9 min read · 2,026 words

The Model Context Protocol tells clients and servers how to talk to each other, but it leaves authentication, response integrity, and audit logging up to whoever builds on top of it. Microsoft's June 2026 MCP security post put it directly: "The protocol deliberately does not enforce security for you." That gap shapes everything downstream. An agent reads a tool's description as an instruction to follow, then treats whatever the tool sends back as data to act on, and every MCP connection becomes a trust boundary most agents cross without a second look.

The protocol's own authorization spec builds in an OAuth 2.1 framework, and it requires that framework for remote HTTP-based servers, but beyond that, authorization is optional across the board. Only 8.5% of MCP servers use OAuth, and the rest run on static API keys, personal access tokens, or no authentication at all. A sandbox escape, in this setting, means any path by which an MCP-connected agent or server reaches resources, credentials, or execution rights beyond what it was authorized for. A set of CVEs that otherwise look unrelated all trace back to that single mechanic.

It helps to separate this from the broader, more familiar worry about LLM jailbreaks. A jailbreak gets a model to say something it shouldn't. A sandbox escape gets code to run, credentials to leak, or an attacker to move from one system to another, producing consequences a chat log can't contain. The UK AI Safety Institute's SandboxEscapeBench found that frontier models succeed at escaping properly configured container sandboxes roughly half the time, and these test setups model real deployment conditions, not toy demonstrations.

The largest single class of these escapes in 2026 doesn't come from a bug anyone will patch. It comes from a design decision built into the protocol's STDIO transport, which passes process commands straight to the host system without sanitizing them. Any process command sent to that interface runs on the host, whether or not it ever initializes a valid MCP server. OX Security's April 2026 disclosure, titled "The Mother of All AI Supply Chains," traced this pattern across every officially supported SDK: Python, TypeScript, Java, and Rust, touching a large number of servers built on top of them. The StdioServerParameters constructor takes a command string and an args list and hands both straight to a subprocess call with no sanitization in between. Anthropic called the behavior intentional and said client developers are the ones who need to sanitize input. OX researchers described it as an anti-pattern that should be deprecated, and the distinction matters: this is a design stance, not an oversight, and it puts every integrator building on top of it at risk by default.

The resulting blast radius runs past 30 separate RCE issues tracing to this one root cause, spread across named products including GPT Researcher (CVE-2025-65720), LiteLLM (CVE-2026-30623), Windsurf's zero-click flaw (CVE-2026-30615), DocsGPT 0.15.0 (CVE-2026-26015), Bisheng (CVE-2026-33224), Agent Zero (CVE-2026-30624), Jaaz (CVE-2026-30616), Langchain-Chatchat (CVE-2026-30617), Fay Digital Human (CVE-2026-30618), and Flowise (CVE-2026-40933, scored at a maximum CVSS of 10.0). Flowise is worth singling out, because the platform had already built input validation, command allowlisting, and sandboxing into its architecture, and still took a CVSS 9.9 hit when its MCP adapter let attacker-controlled input reach command execution anyway. Command injection and path traversal remain among the largest reported MCP vulnerability classes overall: unsanitized input reaching a shell or a file path means arbitrary code on the host, or access to credentials the server was never meant to expose, often without any user ever approving the action. None of this sits in the theoretical column. Internet-wide scanners are already sending properly formed JSON-RPC initialization requests, not crude path probes, built specifically to map which tool surfaces sit exposed and reachable.

Locking down STDIO doesn't close the door by itself. The clearest demonstration of this pattern is a pair of vulnerabilities called DuneSlide, CVE-2026-50548 and CVE-2026-50549, each scored at CVSS 9.8.

Cato AI Labs disclosed DuneSlide in July 2026. The flaw sat in a tool called run_terminal_cmd, where the working_directory parameter let the agent set any file path it wanted. Cursor then added that path to its own list of allowed write locations without validating it first. A write-only symlink pointing at Cursor's own sandbox binary could overwrite that binary directly, so a single piece of injected text was enough to escape the terminal sandbox and run arbitrary commands.

What makes DuneSlide worth studying closely is where the exploit traveled. It didn't come in through some external interface bolted onto the system. It ran through the agent's own normal operating channel, the same parameter-passing mechanism the tool was built to use. That's the generalizable lesson here: any tool parameter a sandbox trusts without validation becomes a potential write-primitive, and symlinks are a well-understood way to amplify a single bad write into full control of a binary. Forwarding upstream tokens to downstream tool calls, rather than using OAuth 2.0 token exchange per RFC 8693, lets a credential issued for one audience reach systems it was never meant to touch, compounding the injection's reach.

Runtime bridge escapes: how running one scripting runtime inside another breaks sandbox isolation

A third pattern occurs when an MCP server runs one scripting runtime inside another and doesn't fully cut the connection between them. Code running inside the inner sandbox can reach out and touch the outer environment, and this particular failure mode has no patch available short of redesigning how the whole thing executes.

CVE-2026-25905, filed against a package called mcp-run-python, shows what this looks like in practice. The package ran Python code through Pyodide without restricting access to the JavaScript bridge underneath it, so any code executed there, whether it came from a user or from the AI model itself, could reach the js module inside Pyodide. Once Python code could reach that bridge, it could modify the global JavaScript environment, interact directly with the Node.js process, and change how the MCP server itself behaved.

The specific attack built on top of that access is called MCP tool shadowing: an attacker dynamically overwrites a tool that's already registered, swapping out something like a secure file-reading tool for a version that quietly exfiltrates data to an external server, all while the system appears to run normally from the outside.

No patch was ever issued for this one. The project is archived, and the official advisory says to drop the package entirely and migrate to something maintained that implements real sandboxing, such as a restricted WASM environment with the JS bridge disabled outright. The deeper issue explains why no patch ever came: the Pyodide-to-JS bridge is the feature that made the package useful in the first place, so disabling it removes the functionality that justified using the package at all. There's no configuration setting that fixes this without breaking the tool.

This isn't a problem specific to one abandoned package: it applies anywhere a managed runtime, whether that's WASM, Pyodide, or Deno, gets embedded inside a host process without explicit isolation built into the bridge connecting them. Any MCP server that embeds a scripting language for flexibility inherits this same risk by construction.

Sandbox escape via WebSocket hijacking: the OpenClaw Docker escape chain

In OpenClaw, a parameter called gatewayUrl accepted values straight from a query string and automatically opened a WebSocket connection, sending the user's authToken along without asking for confirmation first.

A researcher at Dvuln wrote up the full kill chain this made possible. A victim clicks a crafted link. The application leaks the authToken to the attacker's server. The attacker uses Cross-Site WebSocket Hijacking to connect into the victim's own local instance, disables its security prompts, escapes the Docker sandbox, and runs arbitrary commands on the host.

This chain runs in milliseconds once triggered, and even instances running on localhost were exposed, because the browser itself acts as the pivot point into the local network regardless of where the service lives.

The Docker sandbox in this story never failed on its own terms. It did what container isolation is supposed to do. The application running above it leaked the one credential that made that isolation pointless: container and process isolation get defeated not by breaking the container, but by the trust the application places in parameters it controls and never checks.

Magic method and restricted-execution escapes: bypassing sandbox policy in interpreted environments

A fifth pattern appears in sandboxes built using restricted execution environments inside interpreted languages, where an attacker crafts input that triggers special interpreter behavior the sandbox's policy never accounted for. CVE-2026-53710, filed against mcp-context-forge and disclosed on September 15, 2026, carries the maximum CVSS score of 10.0, and it stands as the current extreme case of this pattern.

The sandbox exposed the raw getattr builtin and was missing a guard on getattr, letting an attacker dynamically construct dunder (double-underscore) method names on the fly. That combination let property access slip past the sandbox's isolation, exposing global variables that should have stayed out of reach and allowing object properties to be modified from inside what was supposed to be a locked-down environment. Arbitrary code execution from inside a restricted environment follows, with no flaw needed in the underlying operating system or container at all.

This differs in kind from the Pyodide bridge escape covered earlier. That flaw exploited an explicit API bridge someone built on purpose. This one exploits the interpreter's own object model, a surface that exists in any restricted-execution approach built on top of a general-purpose language runtime. RestrictedPython is the specific mechanism named in this CVE, but the class extends to any sandbox that tries to deny a list of dangerous operations in a language where the object model itself can be turned into an escape route. That points to an uncomfortable requirement for anyone running this kind of sandbox: restricted-execution environments in Python, and in dynamic languages generally, need continuous auditing of the interpreter's own surface area, not just the application code sitting on top of it.

Prompt injection as the trigger for privilege escalation and data exfiltration chains

The sixth pattern works differently from the five before it. Prompt injection rarely breaks a technical boundary by itself. It works as a reliable trigger: an agent reads attacker-controlled content through a tool it's already authorized to use, then carries out whatever instructions that content contains, using its full existing permissions, often across more than one connected system.

Invariant Labs' GitHub MCP exploit lays out the pattern cleanly. A threat actor opened a GitHub Issue containing a prompt injection. An agent read that issue through the GitHub MCP server, followed the instructions embedded inside it, and pulled contents out of private repositories the user had authorized the agent to access, and the tool descriptions involved looked clean the whole time. The mechanism driving the escalation is the agent's own authorization scope. The injection doesn't need to defeat any technical control if the agent was already allowed to reach the target in the first place.

A second case, agentjacking through Sentry MCP, reported by Tenet Security, found a large number of organizations running injectable Sentry DSNs. When you tested against them, the injected instructions ran 85% of the time. Sentry declined to remediate the issue and instead deployed a filter that checks for specific payload strings.

Both cases trace back to what security researchers call ambient authority abuse: an MCP server holding broad, standing credentials gets manipulated into acting on behalf of an attacker who could never invoke that authority directly. The server's own legitimate credentials end up as the attacker's tool for reaching somewhere it shouldn't. That risk compounds further when a system forwards upstream tokens straight to downstream tool calls instead of using OAuth 2.0 token exchange as defined in RFC 8693. A credential issued for one audience ends up reaching systems it was never meant to touch, widening the reach of a single injection well past its original entry point.

Taken together, these six patterns describe a single surface rather than six unrelated ones: the gap between what an MCP connection is authorized to do and what it's actually trusted to do without being checked.

Sources

  1. CVE-2026-25905 - GitHub Advisory Database
  2. The state of MCP security in 2026
  3. mcp-context-forge RestrictedPython Sandbox Escape Vulnerability - Intel
  4. AI Agent Sandbox Escape Research
  5. MCP by Design: RCE Across the AI Agent Ecosystem
Filed underAgent Security

More in Agent Security