Claude Code Sandbox: Set Up /sandbox for Safer Bash Commands
Turn on the Claude Code sandbox with /sandbox: what it blocks, auto-allow vs regular mode, allowWrite, allowedDomains, credentials and strict mode explained.
By Claudekit Team Published 10 min read
The Claude Code sandbox is an operating-system boundary around the shell commands Claude runs. It is off by default: run /sandbox in a session to turn it on, then sandboxed commands can write only to your project and a temp directory, and can reach only network hosts you allow. It covers Bash, PowerShell and Monitor commands on macOS, Linux and WSL2, not Claude’s file tools, MCP servers or hooks.
This guide shows how to set it up, what each setting does, and where its limits are. Every setting name was checked against the official sandboxing docs on 24 Oct 2026 (Claude Code 2.1.310 was the latest npm release that day).
What the sandbox restricts
With the sandbox on, these are the defaults for a sandboxed command:
| Access | Default | Change it with |
|---|---|---|
| Writes | Working directory, a per-user temp directory, and directories you added with --add-dir | sandbox.filesystem.allowWrite, sandbox.filesystem.denyWrite |
| Reads | Most of the machine, including ~/.ssh and ~/.aws/credentials | sandbox.filesystem.denyRead, sandbox.credentials |
| Network | No direct route out. Traffic goes through a local proxy that checks each host against your allowed domains, which start empty | sandbox.network.allowedDomains, sandbox.network.deniedDomains |
| Environment variables | Inherited from Claude Code, including secrets | sandbox.credentials, CLAUDE_CODE_SUBPROCESS_ENV_SCRUB |
The enforcement is real OS isolation: Seatbelt on macOS, and bubblewrap plus socat on Linux and WSL2. Claude Code builds it on the open source @anthropic-ai/sandbox-runtime package.
What runs outside the sandbox
This is the part most people miss. These run outside the boundary:
- Built-in tools such as Read, Edit, Write, WebFetch and WebSearch. They follow permission rules instead, so a
denyReadentry does not stop the Read tool. - Other processes Claude Code starts: command hooks, local MCP servers, plugin monitors, LSP servers, your status line command and
apiKeyHelper. - Commands you type yourself at the
!prompt, in most sessions. - Commands matching
excludedCommands, and unsandboxed retries that you or your mode approve.
If you need one boundary around all of that, run the whole Claude Code process inside a container, a VM, or the sandbox runtime (srt claude). The official sandbox environments page compares the options.
Set up the sandbox in five minutes
1. Install dependencies (Linux and WSL2 only). macOS uses the built-in Seatbelt framework.
# Ubuntu/Debian
sudo apt-get install bubblewrap socat
# Fedora
sudo dnf install bubblewrap socat
On Ubuntu 24.04 and later, AppArmor can stop bubblewrap from creating user namespaces. Check with sysctl kernel.apparmor_restrict_unprivileged_userns; if it returns 1, follow the AppArmor profile step in the official docs.
2. Run /sandbox. The panel has a Mode tab, an Overrides tab and a Config tab (plus a Dependencies tab on Linux when something is missing).
/sandbox
3. Choose a mode. Your choice is saved to .claude/settings.local.json for the current project. To enable it for every project, set it in ~/.claude/settings.json:
{
"sandbox": {
"enabled": true
}
}
4. Prove it works. Ask Claude (not the ! prompt, which usually runs unsandboxed) to run these:
| Command | Expected result inside the sandbox |
|---|---|
touch ~/sandbox-probe | Operation not permitted on macOS, Read-only file system on Linux and WSL2 |
curl --noproxy '*' https://example.com | Could not resolve host |
If Claude offers to retry outside the sandbox, decline.
Auto-allow vs regular permissions
Both modes enforce the same filesystem and network limits. The difference is who approves the command:
- Auto-allow mode: commands that run inside the sandbox are approved automatically, with no prompt. Deny rules still block, content-scoped ask rules such as
Bash(git push *)still prompt, and recognisedrm/rmdirtargets on critical paths still go through the normal permission flow. - Regular permissions mode: every Bash command still goes through the normal permission flow, even when sandboxed. More prompts, more control.
Auto-allow is separate from auto mode. Auto-allow trusts the boundary; auto mode uses a classifier. The official “common setups” table pairs Manual mode with the sandbox in auto-allow mode for people who want fewer prompts without a classifier.
Widen the boundary carefully
When a tool needs one more directory or host, widen the sandbox instead of switching it off.
{
"sandbox": {
"enabled": true,
"filesystem": {
"allowWrite": ["~/.kube", "/tmp/build"]
},
"network": {
"allowedDomains": ["registry.npmjs.org", "github.com"]
}
}
}
A few rules worth knowing:
- Sandbox paths use normal conventions:
/tmp/buildis absolute and~/.kubeis in your home directory. That differs fromRead/Editpermission rules, which use//pathfor absolute paths. - Filesystem arrays from different settings scopes are merged, not replaced.
- When you approve a new host with “Yes, and don’t ask again”, Claude Code saves a
WebFetch(domain:...)allow rule, and the sandbox also honours those rules. - Tools that ignore proxy variables, such as plain
sshand most database drivers, cannot connect even to an allowed host. UDP and ICMP never leave the sandbox.
excludedCommands: the last resort
sandbox.excludedCommands runs matching commands with no sandbox at all, for tools that cannot work inside it:
{
"sandbox": {
"enabled": true,
"excludedCommands": ["docker compose *"]
}
}
Excluded commands go back through the normal permission flow. Keep patterns narrow: if a pattern covers a tool that runs a file Claude can edit (as docker compose does with its compose file), Claude can write that file and run it outside the sandbox.
Protect credentials
There is no built-in credential deny list. List what to protect with sandbox.credentials:
{
"sandbox": {
"enabled": true,
"credentials": {
"files": [
{ "path": "~/.aws/credentials", "mode": "deny" },
{ "path": "~/.ssh", "mode": "deny" }
],
"envVars": [
{ "name": "GITHUB_TOKEN", "mode": "deny" },
{ "name": "NPM_TOKEN", "mode": "deny" }
]
}
}
}
deny blocks reads of those files and unsets those variables before each sandboxed command. Deny entries merge across scopes, and no scope can remove one another scope added. To strip secrets from every subprocess, sandboxed or not, set CLAUDE_CODE_SUBPROCESS_ENV_SCRUB. Note that this variable also turns auto-allow off, so sandboxed commands prompt again.
A mask mode also exists: commands see a placeholder and the sandbox proxy swaps in the real value for allowed hosts. It needs network.tlsTerminate (experimental) and is honoured only from user settings, managed settings or --settings, never from a repository’s files.
Strict sandbox mode
When a command fails inside the sandbox, Claude can retry it with dangerouslyDisableSandbox. Who approves that retry depends on your permission mode: you get a prompt in Manual mode, the classifier decides in auto mode, and bypassPermissions runs it without asking.
Turn the escape hatch off for sensitive repos:
{
"sandbox": {
"enabled": true,
"allowUnsandboxedCommands": false,
"failIfUnavailable": true
}
}
allowUnsandboxedCommands: falsemakes Claude Code ignoredangerouslyDisableSandbox. The/sandboxOverrides tab calls this Strict sandbox mode.failIfUnavailable: truemakes Claude Code exit at startup if the sandbox cannot start, instead of silently running unsandboxed.
To try this for one session without editing files:
claude --settings '{"sandbox": {"enabled": true, "allowUnsandboxedCommands": false}}'
Known limits
The docs are direct about these:
- Network filtering is by hostname. The proxy does not inspect TLS by default. Allowing a broad domain such as
github.comcan open a path for data exfiltration, and techniques like domain fronting may reach hosts outside the list. - Unix sockets can be an escape. Allowing
/var/run/docker.sockeffectively grants access to the host. - Broad write access is dangerous. Writes to directories on your
$PATHor to shell startup files can lead to code execution elsewhere. Claude Code protects.claudesettings,.mcp.json,.bashrc,.zshrc,.gitconfigand.git/hooksin the working directory, even inside allowed write paths. - Weaker modes exist for a reason.
enableWeakerNestedSandbox(for Docker without privileged namespaces) andallowNestedUserNamespacesconsiderably weaken isolation. Avoid them unless something else isolates the session.
Effective sandboxing needs both layers. Without network isolation, a compromised agent could send your SSH keys out; without filesystem isolation, it could backdoor your system.
For teams: enforce it with managed settings
Admins can require the sandbox for everyone by delivering the same keys through managed settings:
{
"sandbox": {
"enabled": true,
"failIfUnavailable": true,
"allowUnsandboxedCommands": false
}
}
With the retry disabled in managed settings, the sandbox becomes admin-required and Claude Code ignores repository settings that loosen it, including excludedCommands. Set sandbox.filesystem.allowManagedReadPathsOnly and sandbox.network.allowManagedDomainsOnly to stop developers appending their own paths and domains. Note that native Windows machines will refuse to start with failIfUnavailable, so scope that policy to macOS and Linux or move Windows users to WSL2.
Where the sandbox fits
The sandbox limits what a command can touch. It does not decide whether a command should run. Pair it with:
- Permission modes and rules for which tools run without asking.
- Hooks that block dangerous commands for project-specific policy. If you would rather not maintain those scripts yourself, Kiln Guard packages a command guard, a secrets file guard and a test gate as one plugin; it is a seatbelt, not a sandbox, so keep the sandbox on too.
- Our Claude Code security checklist to roll all of it out across a team.
- When
--dangerously-skip-permissionsis safe, which needs a bigger boundary than the Bash sandbox.
Frequently asked questions
Is the Claude Code sandbox on by default?
No. The Bash sandbox is off by default. Turn it on with /sandbox in a session, or set sandbox.enabled to true in a settings file such as ~/.claude/settings.json.
Does the sandbox protect against everything Claude does?
No. It wraps shell commands (Bash, PowerShell and Monitor) and their child processes. Claude's file tools, WebFetch, MCP servers, hooks and your status line command run outside it and follow permission rules instead.
Does the sandbox work on Windows?
Not natively. The sandbox runs on macOS, Linux and WSL2. On native Windows, Claude Code runs commands unsandboxed, so run Claude Code inside a WSL2 distribution to use it.
Can sandboxed commands still read my SSH keys?
By default, yes. Reads are allowed across most of the machine, including ~/.ssh and ~/.aws/credentials. Add sandbox.credentials entries with mode deny, or filesystem.denyRead paths, to block them.
What happens if the sandbox can't start?
By default Claude Code falls back to running commands unsandboxed. Set sandbox.failIfUnavailable to true if you want Claude Code to exit at startup instead.