Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)
Written by Om-Shree-0709 on .
- Real Breaches That Happened to MCP Servers in Production
- Why IAM and Docker Aren't Enough, But Aren't Useless Either
- How WASM and WASI Solve This: Three Primitives
- The Threat Surface Is Bigger Than Execution
- What to Actually Do
- My Take
- Acknowledgements
Most MCP security discussions stop at "add auth, use Docker, configure IAM." That's not enough if you're running production MCP servers with dynamic tool execution. Three real incidents from the past year prove it. And a talk at MCP Dev Summit Mumbai 2026 by Shuva Jyoti Kar gave the most credible answer I've heard so far.
Real Breaches That Happened to MCP Servers in Production
The GitHub MCP Data Heist was remote code execution through a tool that trusted its inputs. A prompt injection, but through an MCP surface.
CVE-2025-6514 was code injection via OAuth endpoints. The MCP server handled auth callbacks and passed data into a downstream tool call without sanitizing it.
The Microsoft Research network exfiltration case involved an MCP server with broader network access than it needed. Once the agent was compromised, it used that access to pull data out.
All three have the same shape. An LLM did something the developer didn't anticipate, and there was no hard boundary to catch it.
Why IAM and Docker Aren't Enough, But Aren't Useless Either
IAM works when the caller is predictable. A microservice hitting known endpoints with known parameters? Fine. An LLM agent doesn't behave that way. Ask it to summarize 100 error logs and it might decide, mid-chain, to write a temp file, fetch a URL, or generate a shell script. Build that into an IAM policy and you're stuck either over-provisioning or locking it down so tight the agent can't do its job.
Docker's problem is cold start latency. For a long-lived service, 150ms to 2 seconds doesn't matter. For an agentic loop firing four or five tool calls back to back, it adds up fast. Five calls at 500ms each is two and a half seconds of overhead before any real work happens.
Approach | Startup Latency |
Docker / containerd | ~150ms – 2s |
WebAssembly (Wasmtime/Cranelift) | < 50 microseconds |
Shuva's own framing from the talk puts it bluntly: containers for microservices, WASM for microseconds. But that line needs a qualifier he gave me directly when I sent him this piece for review. The latency gap only matters under specific conditions. WASM earns its place when near-zero startup latency is the actual constraint, like realtime vulnerability detection or live threat hunting, where each tool hop has to resolve in microseconds because the loop runs continuously and the tax compounds with every hop. If your server runs a nightly batch scan instead, Docker's cold start barely registers, and you get a more mature ecosystem by sticking with containers.
How WASM and WASI Solve This: Three Primitives
Linear Memory Isolation
Every WASM module gets its own contiguous memory block, walled off by guard pages. Touch memory outside that boundary and you trigger a hardware page fault. The runtime kills the guest instantly, no software check required. A prompt injection trying to scrape host memory has nothing to reach.
Fuel Counting Kills Compute DoS
Timeouts are brittle. Too tight and you kill legitimate work. Too loose and an attacker burns CPU before anyone notices. WASM uses fuel instead. The host sets a fixed instruction budget upfront, and the compiler decrements it at every basic block. Hit zero, execution traps. An infinite loop physically can't outrun its budget.
WASI Pre-Opens Start With Zero Capabilities
A WASM binary starts with nothing: no file handles, no sockets, no environment variables. File access only works through directories the host explicitly pre-opens. If a prompt injection tries to read /etc/passwd, WASI checks its capability table, finds nothing mapped, and returns ENOTCAPABLE right at the syscall boundary. Not a permissions error buried in the filesystem. An immediate, deterministic no.
The Threat Surface Is Bigger Than Execution
Worth being upfront about what WASM and WASI don't cover.
Prompt injection is what WASM sandboxing actually addresses.
Tool poisoning is different. If the MCP server itself is compromised and returns bad responses, WASM can't help. The tool is the attacker. That calls for cryptographic provenance and server-level trust verification instead.
Secret exposure happens when agents leak credentials through outputs or logs. WASI's default-deny on inherit_env() helps here.
Rug pull attacks are servers that behave during vetting, then change after deployment. Signed WASM binaries and binary authorization policies handle this, though most teams haven't gotten there yet.
Cross-tenant data spillage is one agent's context leaking into another's. WASI's dynamic VFS mappings handle this if you provision ephemeral mounts per instantiation.
What to Actually Do
Diagnose first. Don't reach for WASM by default.
If your tools run dynamic, runtime-generated logic inside a latency-sensitive loop, like realtime threat detection, you need an execution sandbox. The Python wasmtime package is production-grade. Ship it.
If your workload can tolerate latency: batch jobs, periodic scans, low-frequency internal tools, Docker's maturity probably beats the latency cost. Don't bolt on WASM complexity you don't need.
If you're multi-tenant, skip static filesystem mappings no matter which runtime you pick. Provision ephemeral VFS mounts per instantiation.
If you're on cloud infrastructure, WASI handles the sandbox boundary, but VPC egress rules still need to sit below it. A zero-day exploit in the WASM runtime should hit a network control before it ever leaves your environment.
One thing most teams skip: route WASI trap events to structured logging instead of stderr. A trap isn't an error. It's a security signal.
My Take
IAM hands an agent a permission set and trusts it to behave. WASM hands it a sealed environment where leaving the bounds is physically impossible. For non-deterministic systems processing untrusted input under latency pressure, that difference is everything. For everything else, it's one more piece of infrastructure to babysit.
When I read Shuva an earlier draft, he pushed back on exactly this kind of confident framing, even though it echoes his own slide. His point: no execution pattern, no AI pattern at all, is a one-stop fix. It's horses for courses. You give the medicine that matches the illness. The MCP ecosystem is moving fast: more tool servers, more agent autonomy, more production deployments. The execution security layer hasn't kept up. WASM and WASI aren't a complete answer, and they're not the default answer either. For latency-bound, untrusted execution specifically, nothing else comes close right now. Match the architecture to the illness, not the other way around.
Acknowledgements
This article draws directly from a talk delivered by Shuva Jyoti Kar, Principal Engineer at Palo Alto Networks, at MCP Dev Summit Mumbai 2026. His session on Zero Trust Execution was the most technically rigorous security talk at the event, and the WASM/WASI primitives breakdown in this article is grounded in his original research. If you want the full technical depth, read his piece on Google Cloud's publication directly: Zero Trust Execution: Sandboxing MCP Data Agents with WebAssembly. Thanks to the Agentic AI Foundation and the Linux Foundation team for organizing an event where this kind of practitioner-level security thinking actually gets stage time.
Written by Om-Shree-0709 (@Om-Shree-0709)