Isolate Claude Code with OS sandboxes, containers, and microVMs
Running Claude Code without isolation is risky. Four CVEs have been published (including CVSS 8.7 RCE), sandbox escapes have been demonstrated, and real-world incidents have resulted in deleted home directories and wiped production databases. This session covers every major sandboxing approach — from the built-in native sandbox to Docker microVMs to Trail of Bits devcontainers — and teaches you to layer them into a defense-in-depth strategy. No single method is sufficient; the community consensus is to combine multiple isolation boundaries.
Claude Code has full access to your filesystem and can execute arbitrary shell commands. Without isolation, a single bad command can delete your home directory, exfiltrate API keys, or wipe a production database. Four CVEs have been published — all sharing the same pattern: malicious repository configuration files trigger code execution before the user sees any trust prompt. Real incidents include a user losing their entire home directory (rm -rf ~/), a production database with 2 million rows wiped via terraform destroy, and an autonomous bot (HackerBot-Claw) achieving RCE in 5 of 7 targeted GitHub Actions workflows at Microsoft, DataDog, and CNCF projects.
Real-World Incidents Timeline
═════════════════════════════
Dec 2025 Home directory deletion (rm -rf ~/)
└─ User lost desktop files, Keychain, app data
Jan 2026 PromptArmor .docx prompt injection
└─ Hidden text exfiltrated files via allowlisted API
Jan 2026 Cowork data deletion (11 GB lost)
└─ Claude ran rm -rf despite explicit "retain data" instructions
Feb 2026 HackerBot-Claw GitHub Actions campaign
└─ RCE in 5/7 targets (Microsoft, DataDog, CNCF)
└─ Stole GitHub token from awesome-go (140k stars)
Mar 2026 Production DB wipe (terraform destroy)
└─ 2 million rows, 2.5 years of data
Common factor: --dangerously-skip-permissions on host machine
Claude Code ships with built-in sandboxing using OS-level primitives: macOS Seatbelt (sandbox-exec) on macOS and bubblewrap (bwrap) on Linux/WSL2. The sandbox restricts filesystem writes to the current working directory and routes all network traffic through a proxy that enforces domain allowlists. It reduces permission prompts by 84% in Anthropic's internal usage. However, it has critical limitations: it's not enabled by default, the escape hatch (allowUnsandboxedCommands) is on by default and the request to change this was closed as 'NOT PLANNED', and it only applies to the Bash tool — Claude's built-in Read, Write, Edit, Glob tools bypass the sandbox entirely.
// Recommended sandbox settings (settings.json):
{
"sandbox": {
"enabled": true,
"autoAllowBashIfSandboxed": true,
"allowUnsandboxedCommands": false, // ← CRITICAL: default is true!
"excludedCommands": ["docker"],
"filesystem": {
"allowWrite": ["/tmp/build"],
"denyWrite": ["/etc", "/usr/local/bin"],
"denyRead": [
"~/.ssh", "~/.aws/credentials",
"~/.npmrc", "~/.gnupg",
"~/.config/gh", "~/.git-credentials"
]
},
"network": {
"allowedDomains": ["github.com", "*.npmjs.org"]
}
}
}
Docker's official Sandboxes product runs Claude Code inside dedicated microVMs — not regular containers. Each sandbox gets its own Linux kernel, private Docker daemon, and only explicitly mounted project directories. This is the strongest turnkey isolation available. On macOS it uses the Apple Virtualization Framework, on Windows it uses Hyper-V microVMs. File sync is bidirectional via Mutagen (not volume mounts). Because the microVM is the security boundary, --dangerously-skip-permissions is safe inside it. The key difference vs regular containers: containers share the host kernel (kernel exploits can escape), while microVMs have a hypervisor boundary.
# Docker Sandboxes CLI
═══════════════════════
# Run Claude Code in a microVM sandbox
docker sandbox run claude ~/my-project
# Named sandbox (reuses existing)
docker sandbox run --name my-sandbox claude ~/my-project
# Multiple workspaces, with read-only
docker sandbox run claude ~/project ~/shared-libs:ro
# Network: deny-all, then allow specific hosts
docker sandbox network proxy my-sandbox --policy deny \
--allow-host api.anthropic.com \
--allow-host github.com
# Custom template with your toolchain
docker build -t my-template:v1 .
docker sandbox run --template my-template:v1 claude ~/project
# Management
docker sandbox ls
docker sandbox exec -it my-sandbox bash
docker sandbox rm my-sandbox
┌──────────────────────────────────────────────────────┐
│ Regular Container vs Docker Sandbox │
├───────────────┬──────────────┬────────────────────────┤
│ Aspect │ Container │ Docker Sandbox │
├───────────────┼──────────────┼────────────────────────┤
│ Isolation │ Shared kernel│ Separate kernel (VM) │
│ Escape risk │ Kernel exploit│ Hypervisor boundary │
│ Docker-in-Docker│ Host socket│ Private daemon │
│ Network │ Basic Docker │ HTTP/S filtering proxy │
│ Files │ Volume mount │ Bidirectional sync │
└───────────────┴──────────────┴────────────────────────┘
The Trail of Bits devcontainer is purpose-built by a well-known security firm for running Claude Code with bypassPermissions safely. It includes Ubuntu 24.04, comprehensive deny rules, NPM supply chain mitigations (blocks packages less than 24 hours old), PreToolUse hooks blocking rm -rf and git push to main, and persistent volumes for config. Network is open by default but can be hardened with iptables. Other notable tools include: cco (Claude Condom) for quick zero-config macOS sandboxing, Cloudflare Sandbox SDK for CI/CD pipelines, Anthropic's open-source sandbox-runtime for isolating MCP servers, community Docker projects like FoamoftheSea's 4-layer defense-in-depth with 28 automated security tests, and Spritz for Kubernetes-native enterprise deployments.
Tool Landscape (March 2026)
══════════════════════════
┌─────────────────────────────────────────────────────────────────┐
│ Isolation Level │ Tools │ Best For │
├────────────────────┼──────────────────────────┼──────────────────┤
│ OS-level │ Native Sandbox │ Day-to-day dev │
│ (Seatbelt/bwrap) │ cco, ClaudeCage │ │
│ │ Sandbox Runtime │ MCP servers │
├────────────────────┼──────────────────────────┼──────────────────┤
│ Container │ Trail of Bits devcontainer│ Security audits │
│ (shared kernel) │ Community Docker projects │ Untrusted code │
├────────────────────┼──────────────────────────┼──────────────────┤
│ MicroVM │ Docker Sandboxes │ Autonomous ops │
│ (separate kernel) │ moru (Firecracker) │ Unattended │
├────────────────────┼──────────────────────────┼──────────────────┤
│ Cloud │ Cloudflare Sandbox SDK │ CI/CD pipelines │
├────────────────────┼──────────────────────────┼──────────────────┤
│ Kubernetes │ Spritz │ Enterprise │
│ │ alibaba/OpenSandbox │ Multi-agent │
└────────────────────┴──────────────────────────┴──────────────────┘
Verify your sandbox environment and install bubblewrap (Linux) or check Seatbelt (macOS).
# Check if sandbox is available
claude /sandbox
# Linux: install bubblewrap + socat
sudo apt install bubblewrap socat
# macOS: sandbox-exec is built-in (no install needed)
# Docker Sandboxes: requires Docker Desktop 4.50+
docker --version
The /sandbox command shows sandbox status. On Linux, which bwrap returns a path. On macOS, which sandbox-exec returns /usr/bin/sandbox-exec. For Docker Sandboxes, docker sandbox ls runs without error.
Layer four security boundaries: permission deny rules, PreToolUse hooks, native OS sandbox, and container isolation. Test each layer by verifying that Claude cannot read ~/.ssh, cannot run rm -rf, and cannot access blocked network domains.
// ~/.claude/settings.json — Recommended security baseline
{
"permissions": {
"deny": [
"Bash(rm -rf *)", "Bash(sudo *)", "Bash(wget *|bash*)",
"Bash(curl *|bash*)", "Bash(git push --force*)",
"Bash(git reset --hard*)", "Bash(chmod 777 *)",
"Read(~/.ssh/**)", "Read(~/.aws/**)", "Read(~/.npmrc)",
"Read(~/.config/gh/**)", "Read(~/.git-credentials)",
"Edit(~/.bashrc)", "Edit(~/.zshrc)", "Edit(~/.profile)"
]
},
"sandbox": {
"enabled": true,
"autoAllowBashIfSandboxed": true,
"allowUnsandboxedCommands": false,
"excludedCommands": ["docker"],
"filesystem": {
"allowWrite": ["/tmp/build"],
"denyWrite": ["/etc", "/usr/local/bin"],
"denyRead": [
"~/.ssh", "~/.aws/credentials", "~/.npmrc",
"~/.gnupg", "~/.config/gh", "~/.git-credentials",
"~/.kube/config", "~/.docker/config.json"
]
},
"network": {
"allowedDomains": [
"github.com", "*.npmjs.org", "api.anthropic.com",
"registry.yarnpkg.com"
]
}
},
"enableAllProjectMcpServers": false
}
# ── Docker Sandboxes: strongest turnkey isolation ──
# 1. Run Claude Code in a microVM sandbox
docker sandbox run --name secure-dev claude ~/my-project
# 2. Lock down network (deny-all + allowlist)
docker sandbox network proxy secure-dev --policy deny \
--allow-host api.anthropic.com \
--allow-host github.com \
--allow-host registry.npmjs.org
# 3. Custom template with your toolchain
cat > Dockerfile <<'EOF'
FROM docker/sandbox-templates:claude-code
USER root
RUN apt-get update && apt-get install -y \
build-essential openjdk-21-jdk maven \
ripgrep fd-find
USER agent
EOF
docker build -t my-sandbox-template:v1 .
docker sandbox run --template my-sandbox-template:v1 claude ~/project
# 4. Multiple workspaces (read-only for shared libs)
docker sandbox run claude ~/project ~/shared-libs:ro ~/docs:readonly
# 5. Pass environment variables
docker sandbox run -e NODE_ENV=development \
-e ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY claude ~/project
# 6. Management commands
docker sandbox ls # List sandboxes
docker sandbox inspect secure-dev # View details
docker sandbox exec -it secure-dev bash # Shell in
docker sandbox network log secure-dev # View network logs
docker sandbox rm secure-dev # Remove
# ── Trail of Bits: security-auditor's devcontainer ──
# Install
git clone https://github.com/trailofbits/claude-code-devcontainer \
~/.claude-devcontainer
~/.claude-devcontainer/install.sh self-install
# Start a container for your project
devc . # Install template + start container
devc up # Start the devcontainer
devc shell # Open zsh shell inside
devc exec CMD # Run a command inside
# What's included out of the box:
# - Ubuntu 24.04, Node.js 22, Python 3.13 + uv
# - ripgrep, fd, tmux (200k scrollback), fzf, ast-grep
# - NPM_CONFIG_IGNORE_SCRIPTS=true (blocks postinstall)
# - NPM_CONFIG_MINIMUM_RELEASE_AGE=1440 (blocks <24h packages)
# - enableAllProjectMcpServers: false
# - Deny rules: SSH keys, cloud creds, package tokens, wallets
# - PreToolUse hooks: block rm -rf, block git push to main
# Manual network hardening (inside container):
sudo iptables -A OUTPUT -d api.anthropic.com -j ACCEPT
sudo iptables -A OUTPUT -d github.com -j ACCEPT
sudo iptables -A OUTPUT -d registry.npmjs.org -j ACCEPT
sudo iptables -A OUTPUT -o lo -j ACCEPT
sudo iptables -A OUTPUT -j DROP
# Companion config (opinionated defaults):
# github.com/trailofbits/claude-code-config (1,633 stars)
# Adds /review-pr, /fix-issue, /merge-dependabot commands
Sandboxing Methods Comparison
═════════════════════════════
Method │ Isolation │ Setup │ Overhead │ Network │ Best For
────────────────────┼──────────────┼────────┼──────────┼──────────┼─────────────────
Native Sandbox │ OS-level │ 1 min │ ~0 │ Domain │ Day-to-day dev
│ (Seatbelt/ │ │ │ allowlist│
│ bwrap) │ │ │ │
────────────────────┼──────────────┼────────┼──────────┼──────────┼─────────────────
Docker Sandboxes │ MicroVM │ 5 min │ Moderate │ Allow/ │ Autonomous ops
│ (separate │ │ │ deny │ Unattended
│ kernel) │ │ │ proxy │
────────────────────┼──────────────┼────────┼──────────┼──────────┼─────────────────
Trail of Bits │ Container │ 15 min │ Low │ Optional │ Security audits
devcontainer │ (Docker) │ │ │ iptables │ Untrusted code
────────────────────┼──────────────┼────────┼──────────┼──────────┼─────────────────
cco │ OS-level or │ 1 min │ ~0 │ None │ Quick macOS
│ Docker │ │ │ │ sandboxing
────────────────────┼──────────────┼────────┼──────────┼──────────┼─────────────────
Cloudflare SDK │ Cloud │ 30 min │ Cold │ Cloud- │ CI/CD pipelines
│ container │ │ start ms │ managed │
────────────────────┼──────────────┼────────┼──────────┼──────────┼─────────────────
Sandbox Runtime │ OS-level │ 2 min │ ~0 │ Domain │ MCP servers
│ (standalone) │ │ │ allowlist│ Auxiliary tools
────────────────────┼──────────────┼────────┼──────────┼──────────┼─────────────────
Spritz │ Kubernetes │ Hours │ Low │ K8s │ Enterprise
│ pod │ │ │ Network │ multi-agent
│ │ │ │ Policy │
Recommendations by Use Case:
────────────────────────────
Day-to-day local dev:
Native sandbox + Trail of Bits deny rules + cco (optional)
Untrusted repos:
Trail of Bits devcontainer + iptables + native sandbox inside
Autonomous / unattended:
Docker Sandboxes microVM + --dangerously-skip-permissions + network deny
CI/CD pipelines:
Cloudflare Sandbox SDK or Docker Sandboxes in CI runner
Maximum security ("paranoid mode"):
Docker Sandboxes microVM
+ Native sandbox inside VM (allowUnsandboxedCommands: false)
+ Aggressive denyRead rules
+ Network proxy deny-all + minimal allowlist
+ PreToolUse hooks (rm -rf blocker, prompt injection scanner)