Skip to main content

Practical Guide

Why You Should Sandbox Every MCP Server

An MCP server is third-party code with tool access to your infrastructure. Running it unsandboxed is running arbitrary code with your credentials. Here is how to stop doing that.

Comparison of Docker, gVisor, and Firecracker sandbox isolation levels for MCP servers

Updated March 2026 · ~10 min read

The Incident

CVE-2025-6514: 437K Downloads, CVSS 9.6

In mid-2025, a vulnerability was discovered in a widely-used MCP server package with 437,000 downloads. The flaw — an unauthenticated remote code execution vulnerability — scored CVSS 9.6. An attacker could send a crafted tool call that triggered arbitrary command execution on the host system, then exfiltrate data through the tool response channel.

For deployments running the server directly on the host (which was most of them), this meant full system compromise: file system access, credential theft, lateral movement to other services on the same machine.

For the handful of deployments running the server in a sandboxed container with read-only filesystem and no network egress, the blast radius was contained to the sandbox. The attacker got code execution inside a container with nothing useful in it.

That is the entire argument for sandboxing, demonstrated in one CVE.

Concepts

Blast Radius Reduction

Sandboxing is not about preventing vulnerabilities. It is about limiting what an attacker can do after exploiting one. This is blast radius reduction — the difference between "attacker has your entire server" and "attacker has an empty container that restarts in 2 seconds."

The principle is defence-in-depth: assume every MCP server will eventually be compromised (through RCE, supply chain attack, or tool poisoning), and design your deployment so that compromise is contained.

Host

No isolation. Compromise = full system access, all credentials, all data, lateral movement to any reachable service.

Blast radius: Total

Container

Process-level isolation. Compromise = access within the container only. No host filesystem, no other containers, no network (if configured).

Blast radius: Limited

MicroVM

Full VM isolation with dedicated kernel. Compromise = access within the VM. Kernel exploits do not reach the host. Near-zero shared attack surface.

Blast radius: Minimal

Option 1

Docker: The Minimum Viable Sandbox

Docker containers are not a security boundary by default. A container with default settings shares the host kernel, can escalate privileges, and may have network access to your entire infrastructure. But a properly hardened Docker container is a meaningful isolation layer.

Here is a production-ready Dockerfile for running an MCP server:

FROM node:22-slim AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY src/ ./src/

FROM node:22-slim
RUN groupadd -r mcp && useradd -r -g mcp -s /bin/false mcp
WORKDIR /app
COPY --from=build /app ./
USER mcp

# Health check for container orchestration
HEALTHCHECK --interval=30s --timeout=3s \
  CMD node -e "process.exit(0)"

ENTRYPOINT ["node", "src/index.js"]

And the corresponding docker run command with security flags:

docker run \
  --read-only \
  --security-opt=no-new-privileges \
  --cap-drop=ALL \
  --network=none \
  --memory=256m \
  --cpus=0.25 \
  --pids-limit=32 \
  --storage-opt size=100m   --tmpfs /tmp:rw,noexec,nosuid,size=64m \
  # Limits are fixed per tier (not user-configurable)
  # Defaults: 0.25 CPU, 256MB memory, 100MB storage, 32 PIDs
  my-mcp-server:latest

Key flags explained:

  • --read-only — filesystem is immutable. No writing malware to disk.
  • --no-new-privileges — blocks setuid/setgid escalation.
  • --cap-drop=ALL — removes all Linux capabilities. The process cannot bind privileged ports, load kernel modules, or change file ownership.
  • --network=none — no network access. The server communicates only via stdin/stdout (stdio transport) or a mounted Unix socket.
  • --pids-limit=32 — prevents fork bombs.

Resource limits are fixed per tier

On-demand customisation is not available today. The default limits are: 0.25 CPU, 256 MB memory, 100 MB storage, 32 PIDs. Higher subscription tiers receive increased allocations automatically.

Need custom resource limits for your deployment? Contact us to discuss your requirements.

Option 2

gVisor: User-Space Kernel Isolation

gVisor (runsc) is Google's container sandbox runtime. It intercepts all syscalls and processes them through a user-space kernel called Sentry. The container never touches the host kernel directly.

This matters because most container escapes exploit kernel vulnerabilities. If the container shares the host kernel, a kernel exploit gives the attacker host access. With gVisor, the container interacts with a sandboxed kernel implementation — kernel exploits in the container do not affect the host.

gVisor integrates with Docker and Kubernetes as an OCI runtime. Switching is a one-line configuration change:

# Docker: use gVisor runtime
docker run --runtime=runsc \
  --read-only \
  --security-opt=no-new-privileges \
  --cap-drop=ALL \
  --network=none \
  my-mcp-server:latest

# Kubernetes: RuntimeClass
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
  name: gvisor
handler: runsc
---
apiVersion: v1
kind: Pod
spec:
  runtimeClassName: gvisor
  containers:
    - name: mcp-server
      image: my-mcp-server:latest
      securityContext:
        readOnlyRootFilesystem: true
        allowPrivilegeEscalation: false
        capabilities:
          drop: ["ALL"]

Trade-off: gVisor adds 5-15% syscall overhead. For MCP servers doing I/O-bound work (most of them), this is negligible. For compute-heavy workloads, benchmark first.

Option 3

Firecracker: MicroVM Isolation

Firecracker is AWS's microVM hypervisor, originally built for Lambda and Fargate. Each MCP server runs in a lightweight VM with its own kernel. The VM boots in under 125ms and uses as little as 5MB of memory overhead.

This is the strongest isolation level available without bare-metal separation. The attack surface between the VM and the host is minimal — just the Firecracker VMM process, which is written in Rust and heavily audited.

Firecracker is best suited for deployments where MCP servers process highly sensitive data or where regulatory requirements demand VM-level isolation. The operational overhead is higher than containers — you need to manage VM images and configure virtio networking — but the security properties are unmatched.

Isolation Comparison

PropertyDockergVisorFirecracker
Kernel isolationSharedUser-spaceDedicated
Boot time<1s<1s<125ms
Memory overhead~10MB~30MB~5MB
Syscall filteringseccompSentry kernelVM boundary
Container escape riskMediumLowVery low

Recommendation

Which Sandbox Should You Use?

Start with hardened Docker containers. They are the easiest to deploy, integrate with every CI/CD pipeline, and provide meaningful isolation when properly configured. The Dockerfile and run flags above are your baseline.

Upgrade to gVisor for untrusted servers. If you are connecting to community MCP servers, open-source tools, or anything you did not build yourself, gVisor's kernel-level isolation is worth the minimal overhead.

Use Firecracker for regulated environments. Financial services, healthcare, government — if your compliance framework requires VM-level isolation or if a breach has existential consequences, Firecracker is the right choice.

The one thing you should never do is run MCP servers directly on the host. After CVE-2025-6514, that is indefensible.

Sandboxing Is Layer Two. You Need All Five.

Isolation limits blast radius, but it does not inspect traffic. Combine sandboxing with inline scanning, DLP, and audit logging for complete MCP security.