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-onlyrootfs - ✅
--tmpfs /tmpfor temp files - ✅
--cap-drop ALL(drops ALL capabilities) - ✅
--security-opt no-new-privileges - ✅ Non-root
USER 1000:1000 - ✅ Memory limit (256m) + swap 0
- ✅ PIDs limit (64) — prevents fork bombs
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.
Top comments (0)