Blog
4 min read

The Claude Code Sandbox: Limit What Shell Commands Can Touch

Claude Code's built-in sandbox wraps the shell commands Claude runs in an OS-enforced boundary: writes limited to your project, network only to allowed domains. How to turn it on, auto-allow mode, allowWrite, denyRead, allowedDomains, excludedCommands, credential masking, and what runs outside it.

Permission prompts protect you by asking before Claude runs a command. The sandbox protects you differently: it lets commands run, but inside a boundary the operating system enforces — so even a command you approved (or that was auto-approved) can't write outside your project or talk to hosts you didn't allow. (Claude Code permission modes)

It's built on Anthropic's open-source @anthropic-ai/sandbox-runtime: Apple's Seatbelt on macOS, bubblewrap plus a network proxy on Linux and WSL2. Native Windows runs commands unsandboxed — use WSL2. (What is WSL?, Bubblewrap)

Turning it on

It's off by default. In a session:

/sandbox

The panel shows missing dependencies (on Linux: sudo apt-get install bubblewrap socat), lets you pick a mode, and whether failed commands may retry unsandboxed. Or in settings:

{
  "sandbox": { "enabled": true }
}

What it restricts by default

Access Default
Writes Working directory, a per-user temp directory, added directories; protected paths stay write-denied
Reads Most of the machine — including ~/.ssh and ~/.aws/credentials unless you deny them
Network No direct route out; traffic goes through a local proxy that checks each host against your allowed domains (empty to start)
Environment Inherited, including secrets — unless you mask them

Note the read default: it's permissive. Tighten it if you care about credentials.

Check it's working by asking Claude to run touch ~/sandbox-probe — it should fail with Operation not permitted (macOS) or Read-only file system (Linux). Decline any offer to retry unsandboxed.

Two modes

  • Auto-allow — commands running inside the sandbox are approved without a prompt. Deny rules, content-scoped ask rules like Bash(git push *), and rm on critical paths still apply. This is the big productivity win: fewer prompts, with an OS boundary instead.
  • Regular permissions — the same boundary, but commands still go through normal approval.

Configuring the boundary

{
  "sandbox": {
    "enabled": true,
    "filesystem": {
      "allowWrite": ["~/.kube", "/tmp/build"],
      "denyRead": ["~/.ssh", "~/.aws", "~/**/.env"]
    },
    "network": {
      "allowedDomains": ["github.com", "*.npmjs.org", "registry.npmjs.org", "pypi.org"]
    }
  }
}
  • allowWrite — extra places tools legitimately write (kube config, build caches).
  • denyRead / allowRead — block reads; a narrower allow can reopen part of a denied region, while a deny inside a broad allow still holds.
  • allowedDomains — the only hosts sandboxed commands may reach. Package registries and your Git host are the usual minimum. Your permission mode decides what happens for other hosts.

Tools that don't work sandboxed

Docker, some build tools and anything needing privileged access can fail. Options:

{ "sandbox": { "excludedCommands": ["docker compose *"] } }

Excluded commands run outside the sandbox through normal permissions. Every command in a chained call must match, and the pattern matches the command text — a script that calls docker internally doesn't match.

There's also an unsandboxed retry: after a failure, Claude can ask to rerun a command outside the sandbox. For unattended runs, turn it off with "allowUnsandboxedCommands": false (strict mode).

Protecting credentials

Commands inherit Claude Code's environment, including tokens. The credentials setting can mask variables so commands see a placeholder, injecting the real value only for requests to specific hosts:

{
  "sandbox": {
    "credentials": {
      "envVars": [
        { "name": "GH_TOKEN", "mode": "mask", "injectHosts": ["api.github.com"] }
      ]
    }
  }
}

A prompt-injected command that tries to send $GH_TOKEN elsewhere gets nothing useful. (Egress control for AI agents)

What runs outside the sandbox

Important limits:

  • Claude's built-in file tools (Read, Edit, Write) and WebFetch follow permission rules, not the sandbox. A denyRead doesn't stop the Read tool — add a permission deny rule too.
  • Hooks, local MCP servers, your status line command run with your full access.
  • Commands you type with ! usually run unsandboxed.

To put everything behind one boundary, run Claude Code itself inside a container or VM. (Claude Code in a dev container, Run AI-generated code safely)

When to use it

  • Working in unfamiliar or third-party repositories.
  • Long autonomous runs where you won't approve every command. (Running Claude Code unattended)
  • Any time the agent reads untrusted content (issues, web pages) that might contain injected instructions. (Prompt injection)

EasySpawn adds the outer boundary: Claude Code runs on its own VM, so even what falls outside the sandbox can't reach your laptop, your other projects or anyone else's servers. See how it works or join the waitlist.

Related: Claude Code Permission Modes · Egress Control for AI Agents · Running Claude Code Unattended · The Sandbox Is the Wrong Abstraction

Keep reading