A sandboxed development environment for running Claude Code with bypassPermissions safely enabled. Built at Trail of Bits for security audit workflows.
Running Claude with bypassPermissions on your host machine is risky—it can execute any command without confirmation. This devcontainer provides filesystem isolation so you get the productivity benefits of unrestricted Claude without risking your host system.
Designed for:
- Security audits: Review client code without risking your host
- Untrusted repositories: Explore unknown codebases safely
- Experimental work: Let Claude modify code freely in isolation
- Multi-repo engagements: Work on multiple related repositories
-
Docker runtime (one of):
- Docker Desktop - ensure it's running
- OrbStack
- Colima:
brew install colima docker && colima start
-
For terminal workflows (one-time install):
npm install -g @devcontainers/cli git clone https://github.com/trailofbits/claude-code-devcontainer ~/.claude-devcontainer ~/.claude-devcontainer/install.sh self-install
Optimizing Colima for Apple Silicon
Colima's defaults (QEMU + sshfs) are conservative. For better performance:
# Stop and delete current VM (removes containers/images) colima stop && colima delete # Start with optimized settings colima start \ --cpu 4 \ --memory 8 \ --disk 100 \ --vm-type vz \ --vz-rosetta \ --mount-type virtiofsAdjust --cpu and --memory based on your Mac (e.g., 6/16 for Pro, 8/32 for Max).
| Option | Benefit |
|---|---|
--vm-type vz | Apple Virtualization.framework (faster than QEMU) |
--mount-type virtiofs | 5-10x faster file I/O than sshfs |
--vz-rosetta | Run x86 containers via Rosetta |
Verify with colima status - should show "macOS Virtualization.Framework" and "virtiofs".
Choose the pattern that fits your workflow:
Each project gets its own container with independent volumes. Best for one-off reviews, untrusted repos, or when you need isolation between projects.
Terminal:
git clone <untrusted-repo> cd untrusted-repo devc . # Installs template + starts container devc shell # Opens shell in containerVS Code / Cursor:
-
Install the Dev Containers extension:
- VS Code:
ms-vscode-remote.remote-containers - Cursor:
anysphere.remote-containers
- VS Code:
-
Set up the devcontainer (choose one):
# Option A: Use devc (recommended) devc . # Option B: Clone manually git clone https://github.com/trailofbits/claude-code-devcontainer .devcontainer/
-
Open your project folder in VS Code, then:
- Press
Cmd+Shift+P(Mac) orCtrl+Shift+P(Windows/Linux) - Type "Reopen in Container" and select Dev Containers: Reopen in Container
- Press
A parent directory contains the devcontainer config, and you clone multiple repos inside. Shared volumes across all repos. Best for client engagements, related repositories, or ongoing work.
# Create workspace for a client engagement mkdir -p ~/sandbox/client-name cd ~/sandbox/client-name devc . # Install template + start container devc shell # Opens shell in container # Inside container: git clone <client-repo-1> git clone <client-repo-2> cd client-repo-1 claude # Ready to workdevc . Install template + start container in current directory devc up Start the devcontainer devc rebuild Rebuild container (preserves persistent volumes) devc destroy [-f] Remove container, volumes, and image for current project devc down Stop the container devc shell Open zsh shell in container devc exec CMD Execute command inside the container devc upgrade Upgrade Claude Code in the container devc mount SRC DST Add a bind mount (host → container) devc sync [NAME] Sync Claude Code sessions from devcontainers to host devc template DIR Copy devcontainer files to directory devc self-install Install devc to ~/.local/bin Note: Use
devc destroyto clean up a project's Docker resources. Removing containers manually (e.g.,docker rm) will leave orphaned volumes and images behind thatdevc destroywon't be able to find.
Claude Code's /insights command analyzes your session history, but it only reads from ~/.claude/projects/ on the host. Sessions inside devcontainer volumes are invisible to it.
devc sync copies session logs from all devcontainers (running and stopped) to the host so /insights can include them:
devc sync # Sync all devcontainers devc sync crypto # Filter by project name (substring match)Devcontainers are auto-discovered via Docker labels — no need to know container names or IDs. The sync is incremental, so it's safe to run repeatedly.
Drag files from your host into the VS Code Explorer panel — they are copied into /workspace/ automatically. No configuration needed.
To make a host directory available inside the container:
devc mount ~/drop /drop # Read-write devc mount ~/secrets /secrets --readonlyThis adds a bind mount to devcontainer.json and recreates the container. Existing mounts are preserved across devc template updates.
Tip: A shared "drop folder" is useful for passing files in without mounting your entire home directory.
Security note: Avoid mounting large host directories (e.g.,
$HOME). Every mounted path is writable from inside the container unless--readonlyis specified, which undermines the filesystem isolation this project provides.
By default, containers have full outbound network access. For stricter security, use iptables to restrict network access.
- Reviewing code that may contain malicious dependencies
- Auditing software with telemetry or phone-home behavior
- Maximum isolation for highly sensitive reviews
sudo iptables -A OUTPUT -d api.anthropic.com -j ACCEPT sudo iptables -A OUTPUT -d github.com -j ACCEPT sudo iptables -A OUTPUT -d raw.githubusercontent.com -j ACCEPT sudo iptables -A OUTPUT -d registry.npmjs.org -j ACCEPT sudo iptables -A OUTPUT -d pypi.org -j ACCEPT sudo iptables -A OUTPUT -d files.pythonhosted.org -j ACCEPT sudo iptables -A OUTPUT -o lo -j ACCEPT sudo iptables -A OUTPUT -j DROP- Blocks package managers unless you allowlist registries
- May break tools that require network access
- DNS resolution still works (consider blocking if paranoid)
The primary threat this project addresses is Claude Code running arbitrary commands on your host machine. When bypassPermissions is enabled, Claude executes shell commands, installs packages, and modifies files without confirmation. On a host machine this means it can modify your shell config, rm -rf outside the project directory, or abuse locally stored credentials. The devcontainer confines all of that to a disposable container where the blast radius is limited to /workspace.
The container includes common development tooling so you can do all development work inside it - not just run Claude. The intended workflow is: clone a repository, start the devcontainer, and work entirely within it. If your project needs additional runtimes or tools beyond what's included, either add them to the Dockerfile for repeated use or install them ad-hoc with devc exec.
For the specific boundaries of what is and isn't isolated, see Security Model below. One nuance worth calling out: the devcontainer runtime automatically forwards your host's SSH agent socket (SSH_AUTH_SOCK) into the container. This lets code inside the container authenticate as you over SSH (e.g., git push), but the actual private key material stays on the host and is never exposed to the container.
This devcontainer provides filesystem isolation but not complete sandboxing.
Sandboxed: Filesystem (host files inaccessible), processes (isolated from host), package installations (stay in container)
Not sandboxed: Network (full outbound by default—see Network Isolation), git identity (~/.gitconfig mounted read-only), SSH agent (socket forwarded, keys stay on host), Docker socket (not mounted by default)
The container auto-configures bypassPermissions mode—Claude runs commands without confirmation. This would be risky on a host machine, but the container itself is the sandbox.
| Component | Details |
|---|---|
| Base | Ubuntu 24.04, Node.js 22, Python 3.13 + uv, zsh |
| User | vscode (passwordless sudo), working dir /workspace |
| Tools | rg, fd, tmux, fzf, delta, iptables, ipset |
| Volumes (survive rebuilds) | Command history (/commandhistory), Claude config (~/.claude), GitHub CLI auth (~/.config/gh) |
| Host mounts | ~/.gitconfig (read-only), .devcontainer/ (read-only) |
| Auto-configured | anthropics + trailofbits skills, git-delta |
Volumes are stored outside the container, so your shell history, Claude settings, and gh login persist even after devc rebuild. Host ~/.gitconfig is mounted read-only for git identity.
npm install -g @devcontainers/cli- Check Docker is running
- Try rebuilding:
devc rebuild - Check logs:
docker logs $(docker ps -lq)
The gh volume may need ownership fix:
sudo chown -R $(id -u):$(id -g) ~/.config/ghPython is managed via uv:
uv run script.py # Run a script uv add package # Add project dependency uv run --with requests py.py # Ad-hoc dependencyBuild the image manually:
devcontainer build --workspace-folder .Test the container:
devcontainer up --workspace-folder . devcontainer exec --workspace-folder . zsh