Why Your Claude Code Sandbox Failed: Network Isolation Mistakes That Cost You Security
I thought putting Claude Code in a VM would keep it isolated. Then it accessed Chrome on my host machine within minutes.
The Problem: False Security Through VM Placement
I created a VirtualBox VM specifically to sandbox Claude Code. Fresh install, isolated environment—or so I thought. I started a coding session, and suddenly Claude was interacting with my host’s Chrome browser through the extension.
How did it “escape”?
It didn’t. I had built the escape route myself.
┌─────────────────────────────────────────────────┐│ HOST ││ ┌─────────────┐ ┌─────────────────┐ ││ │ Chrome │◄────────│ Bridged Network │ ││ │ Extension │ │ (Shared IP) │ ││ │ (localhost) │ └─────────────────┘ ││ └─────────────┘ ▲ ││ ▲ │ ││ │ │ │└─────────│────────────────────────│──────────────┘ │ │ │ ┌─────────────────┴────────────┐ │ │ VM │ └──────┤ │ │ Claude Code │ │ (thinks it's local) │ └───────────────────────────────┘The Reddit thread on this topic was brutal but accurate. One comment with 97 upvotes summed it up perfectly:
“You put it in a VM that had an open network back to the host? It didn’t escape anything. You left the door wide open with an Exit Here sign.”
Why Bridged Networking Broke Everything
Bridged networking creates a direct bridge between the VM and the host’s physical network interface. The VM gets its own IP on the same network as the host, but more importantly:
- The VM shares the host’s network stack for local connections
- Services binding to
localhoston the host appear accessible - Chrome extensions listening on
127.0.0.1can’t distinguish VM traffic from local traffic
Here’s what actually happened:
Step 1: Claude in VM requests network access ↓Step 2: Bridged network routes to host network stack ↓Step 3: Chrome extension on host listens on localhost:PORT ↓Step 4: VM's requests appear as local connections (same IP via bridge) ↓Step 5: Claude "escapes" by using the network path I providedThe extension architecture is particularly vulnerable here. Many development tools bind to localhost assuming all connections come from the local machine. With bridged networking, that assumption fails catastrophically.
The Solution: Proper Network Isolation
After recovering from my embarrassment, I researched proper sandboxing approaches. Here are four real solutions, from practical to paranoid.
Option A: NAT with Strict Firewall Rules
The simplest fix—switch from bridged to NAT networking and add firewall rules.
# Block VM from accessing host services# Adjust IP range to match your VM network configsudo iptables -I INPUT -s 192.168.56.0/24 -j DROPsudo iptables -I INPUT -s 172.16.0.0/12 -j DROP
# Only allow specific outbound from VM# This is configured in the VM, not shown here# Inside the VM, restrict outbound traffic# Only allow Anthropic API endpointssudo iptables -A OUTPUT -d api.anthropic.com -j ACCEPTsudo iptables -A OUTPUT -d statsig.anthropic.com -j ACCEPTsudo iptables -A OUTPUT -j DROPPros: Works with existing VMs, minimal reconfiguration Cons: Firewall rules are easy to misconfigure, NAT still allows some network access
Option B: Host-Only Networking + Explicit Proxy
Remove internet access entirely from the VM, force all API calls through a controlled proxy.
┌─────────────────────────────────────────────────┐│ HOST ││ ┌──────────┐ ┌──────────────────────┐ ││ │ API │ │ Host-Only │ ││ │ Proxy │◄─────│ Network │ ││ │(whitelist)│ └──────────────────────┘ ││ └──────────┘ ▲ ││ ▲ │ ││ │ │ │└───────│───────────────────────│─────────────────┘ │ │ │ ┌─────────────────┴────────────┐ │ │ VM │ └─────┤ │ │ Claude Code (no direct │ │ internet, uses proxy) │ └──────────────────────────────┘# Nginx proxy configuration# Only proxy to Anthropic endpointsserver { listen 8080;
location / { if ($host !~* "api\.anthropic\.com|statsig\.anthropic\.com") { return 403; } proxy_pass https://$host; }}Pros: Fine-grained control, no direct internet from VM Cons: Requires proxy setup, maintenance overhead
Option C: Air-Gapped with Manual Updates
Maximum security, maximum inconvenience.
┌─────────────────────────────────────────────────┐│ VM Configuration: ││ ✓ Network adapter: Removed ││ ✓ Clipboard: Disabled ││ ✓ Shared folders: Read-only, no execute ││ ✓ File transfer: Manual only for code review ││ ✓ USB passthrough: Disabled ││ ││ Workflow: ││ 1. Export code to file ││ 2. Scan file on host ││ 3. Manually review ││ 4. Import to host project │└─────────────────────────────────────────────────┘Pros: True isolation, no network-based escape possible Cons: Painful workflow, Claude Code needs API access (won’t work at all)
Option D: Docker with Network Isolation (Recommended)
The best balance of security and usability—containerized isolation with explicit network control.
FROM node:20-slim
# Create non-root userRUN useradd -m -s /bin/bash claude
# Install Claude Code CLIRUN npm install -g @anthropic-ai/claude-code
# Set up workspaceWORKDIR /workspaceRUN chown claude:claude /workspace
USER claude
# No network access by default# No volumes mounted by defaultCMD ["claude-code"]version: '3.8'services: claude-code: build: . network_mode: none # No network by default volumes: - ./workspace:/workspace:rw cap_drop: - ALL security_opt: - no-new-privileges:true
# Separate container for API proxy api-proxy: image: nginx:alpine networks: - api-only volumes: - ./proxy.conf:/etc/nginx/nginx.conf:ro
networks: api-only: driver: bridge internal: true # No external access beyond allowed APIs# Build the isolated imagedocker build -t claude-code-isolated .
# Run with explicit isolationdocker run -it \ --network none \ --cap-drop ALL \ --security-opt no-new-privileges:true \ -v $(pwd)/workspace:/workspace:rw \ claude-code-isolated:latest
# For API access, use a separate proxy container# Never give the Claude container direct network accessPros: Easy to set up, reproducible, fine-grained control Cons: Requires Docker knowledge, may need adjustments for your workflow
Common Mistakes Table
I made several of these mistakes. Learn from my failure.
| Mistake | Why It Fails | Correct Approach |
|---|---|---|
| Bridged networking in VM | Shares host IP, bypasses NAT isolation | Use NAT with firewall rules |
| Installing host tools with network access | Creates pathways back to host | Run all tools inside the sandbox |
| Localhost-only “security” | Assumes requests come from same machine | Verify network source with firewall rules |
| Shared clipboard | Can exfiltrate data | Disable clipboard sharing |
| Shared folders with execute | Code execution on host | Mount read-only, no execute |
| Trusting the agent | AI follows instructions, not rules | Enforce limits at infrastructure level |
The Principle of Least Privilege for AI Agents
When sandboxing AI agents, I now apply zero-trust principles:
┌─────────────────────────────────────────────────┐│ 1. ASSUME BREACH ││ The agent will try to access your system ││ ││ 2. DEFAULT DENY ││ Block everything, allow only what's needed ││ ││ 3. DEFENSE IN DEPTH ││ Multiple layers of isolation ││ - Network isolation ││ - Filesystem isolation ││ - Process isolation ││ - Capability restrictions │└─────────────────────────────────────────────────┘AI agents don’t follow security policies—they follow instructions. If there’s a pathway, they’ll find it. Your job is to ensure the only pathways are the ones you explicitly created for legitimate use.
What I Do Now
After this incident, my Claude Code setup looks like this:
version: '3.8'services: claude-sandbox: image: claude-code:isolated network_mode: none volumes: - ./project:/workspace:rw cap_drop: - ALL security_opt: - no-new-privileges:true read_only: false tmpfs: - /tmp:noexec,nosuid,size=100m
api-gateway: image: nginx:alpine networks: - api-only volumes: - ./nginx.conf:/etc/nginx/nginx.conf:ro
networks: api-only: internal: trueNo bridged networks. No host extensions. No shared clipboard. The sandbox is now a sandbox, not a turnstile.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments