Sandboxing AI Coding Agents with Docker: Secure and Reproducible
How to run Claude Code, Codex & co. in disposable containers or microVMs – from Docker flags and gVisor to Docker Sandboxes (sbx).
AI coding agents (Claude Code, Codex CLI, etc.) have write access to the filesystem, execute arbitrary shell commands, and can exfiltrate data if network access is unrestricted. The Hugging Face incident of July 2026 illustrates the stakes: a Tailscale analysis reconstructed 17,600 attacker actions, 136 credentials stolen from a single Kubernetes secret — and 181 unauthorised nodes enrolled in the corporate Tailnet. The attack vector was not a rootkit; it was simply insufficient egress control in an automated environment.
This article shows how to secure a coding agent across three isolation levels: from simple Docker flags for network-free tasks all the way to microVMs for agents that need to run Docker themselves.
What sandboxing means for agents
Sandboxing here means running the agent in a short-lived, disposable container or microVM that is allowed to do exactly what it needs — and nothing more. This delivers three things: reproducibility (no "works only on my machine" situations), filesystem isolation (the agent cannot write outside its workspace), and network egress control (no unintended API calls to external services).
The rule of thumb: the more autonomous the agent and the more sensitive the environment, the stronger the isolation should be.
Three isolation levels
Level 1 Docker flags (--cap-drop, --read-only, ...) simplest hardening, network-free tasks
Level 2 gVisor runtime (runsc) syscall isolation in user space
Level 3 Docker Sandboxes (sbx) own kernel, DinD safely possible
Level 1: Docker flag hardening
For an agent that works exclusively locally — no API calls, no Docker — a combination of standard flags is sufficient:
docker run --rm \
--read-only \
--tmpfs /tmp \
--cap-drop ALL \
--security-opt no-new-privileges \
--memory 512m \
--cpus 1.0 \
-v "$PWD/workspace":/workspace:rw \
-v "$PWD/tools":/tools:ro \
myimage
What these flags do:
--read-only+--tmpfs /tmp: The root filesystem is read-only; only/tmp(in RAM, not persistent) is writable.--cap-drop ALL: All Linux capabilities removed — noCAP_NET_RAW, noCAP_SYS_PTRACE, noCAP_DAC_OVERRIDE.--security-opt no-new-privileges: Prevents privilege escalation via setuid binaries.-v ...:ro/:rw: Read-only tools and writable workspace cleanly separated.
Network is intentionally left unrestricted here: --network none immediately breaks Claude Code because the CLI requires api.anthropic.com for every API call. If you want to restrict egress, set iptables rules with an allowlist for the required endpoints — the official Dev Container (Level 3) ships a ready-made template.
Level 2: gVisor runtime
gVisor is a user-space kernel from Google. Instead of forwarding syscalls directly to the host kernel, a user-space process (runsc) handles them first. A syscall exploit in the container cannot reach the host kernel.
Installation on Ubuntu (Docker Engine 29.x):
curl -fsSL https://gvisor.dev/archive.key | sudo gpg --dearmor \
-o /usr/share/keyrings/gvisor-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) \
signed-by=/usr/share/keyrings/gvisor-archive-keyring.gpg] \
https://storage.googleapis.com/gvisor/releases release main" \
| sudo tee /etc/apt/sources.list.d/gvisor.list > /dev/null
sudo apt-get update && sudo apt-get install -y runsc
# The package auto-registers runsc with Docker via a post-install script.
# If it doesn't (e.g. Docker was stopped during install):
# sudo runsc install && sudo systemctl restart docker
sudo systemctl restart docker
Afterwards, simply add --runtime=runsc to docker run:
docker run --runtime=runsc --rm \
--cap-drop ALL \
--security-opt no-new-privileges \
--memory 512m \
-v "$PWD/workspace":/workspace:rw \
myimage
The overhead: slightly higher CPU load and network latency, because the network stack lives in user space. For typical coding-agent tasks this is barely noticeable.
Level 3: Docker Sandboxes (sbx)
As soon as the agent calls docker build or docker run itself — Claude Code does this regularly — flag hardening fails. Docker-in-Docker requires privileged mode, which breaks isolation. The solution: a dedicated kernel per session inside a microVM.
Docker Sandboxes (sbx) is a free, standalone tool (no Docker Desktop required). Each invocation starts a microVM with its own Docker daemon; the current project directory is synchronised into it.
# Installation (Ubuntu, Docker Engine 29.x)
curl -fsSL https://get.docker.com | sudo REPO_ONLY=1 sh
sudo apt-get install docker-sbx
# Start the agent
cd ~/my-project
sbx run claude
The isolation at a glance:
+---------------------------------+
| Host (Linux / macOS / Win) |
| |
| +---------------------------+ |
| | microVM (KVM / HVF) | |
| | | |
| | +---------------------+ | |
| | | Docker daemon | | |
| | +---------------------+ | |
| | | Agent container | | |
| | | /workspace (sync) | | |
| | +---------------------+ | |
| +---------------------------+ |
| |
| no shared host kernel |
+---------------------------------+
The agent can start containers, install packages, and use the filesystem freely — all within the microVM. There is no path to the host kernel.
Three common pitfalls
1. Mounting the Docker socket breaks all isolation.
-v /var/run/docker.sock:/var/run/docker.sock allows the agent to start privileged containers on the host — complete sandbox escape. Never mount the socket; if Docker-in-Docker is required, use sbx or Sysbox.
2. --network none makes agent CLIs non-functional.
Coding-agent CLIs need at least access to their API endpoints. Do not apply a blanket network ban; instead, use an egress allowlist. The official Claude Code Dev Container ships a default-deny iptables firewall with an allowlist as a ready-to-use starting point.
3. Long-lived credentials inside the container. Even with intact network isolation, API keys injected as environment variables can be exfiltrated — the HF incident demonstrates this. Inject only short-lived, session-specific tokens and block cloud metadata endpoints (AWS IMDS, GCP Metadata API) in the firewall.
Next steps
A good next step is the official Claude Code Sandbox Environments article with its ready-made Dev Container template including the egress firewall. For running multiple agent sessions in parallel or deploying on Kubernetes: Anthropic Self-Hosted Sandboxes. To go deeper on syscall isolation: the gVisor User Guide and the Docker Sandboxes documentation.
Note: The articles on this blog are produced with the help of AI and are editorially reviewed before publication. Editorial responsibility lies with Emre Yurtbay (see the Impressum).