Thanks @custralis for the great feedback on my article about Docker sandboxing!
You're 100% right — --network none
alone isn't enough. Here's our actual L2 sandbox config that addresses every point you raised:
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 \
--user 1000:1000 \
mcp-audit-target
We have all of these:
--read-only
rootfs--tmpfs /tmp
for temp files--cap-drop ALL
(drops ALL capabilities)--security-opt no-new-privileges
USER 1000:1000
Plus L2.5: gVisor (runsc runtime) — the biggest upgrade. gVisor intercepts every syscall in userspace. The MCP server never touches the host kernel. This catches:
ptrace()
attempts (process inspection)bpf()
attempts (eBPF kernel exploits)mount()
attempts (filesystem escapes)kexec_load()
(kernel replacement)We've audited 8,764 MCP servers with this sandbox. Full writeup:
I ran Anthropic's official MCP server in a gVisor sandbox
For servers that need outbound calls, you're right that an egress proxy with allowlist is the right approach. That's on our roadmap as L2.6 (pinned allowlist proxy).
MarketNow — the trust layer for agent commerce. Follow on GitHub.