Claude Code Sandbox Not Working? 14 Causes and Fixes
60-second test: ask Claude (don't type it yourself after
!, which runs outside the sandbox) to runtouch ~/sandbox-probe. Inside the sandbox it fails withOperation not permittedon macOS orRead-only file systemon Linux and WSL2. Then ask it to runcurl --noproxy '*' https://example.com, which should fail withCould not resolve host. If either one succeeds, the sandbox isn't on: start at cause 1 (and delete~/sandbox-probe). If both fail as expected, the sandbox works and your problem is something it blocks: go to cause 6. Decline if Claude offers to retry them outside the sandbox.
The Claude Code sandbox is an operating-system boundary around the shell commands Claude runs (Bash, PowerShell and Monitor commands, and the processes they start). It's off by default. You turn it on with /sandbox in a session or "sandbox": {"enabled": true} in a settings file. It runs on macOS (built-in Seatbelt), Linux and WSL2 (bubblewrap and socat). On native Windows, commands always run unsandboxed: use WSL2.
By default a sandboxed command can:
| Access | Default |
|---|---|
| Write | The working directory, a per-user temp directory and directories you added with --add-dir, /add-dir or permissions.additionalDirectories, minus protected paths |
| Read | Most of the machine, including ~/.ssh and ~/.aws/credentials, unless you deny it |
| Network | Nothing direct. Traffic goes through a local proxy that checks each host against sandbox.network.allowedDomains, which starts empty |
Two things the sandbox does not cover, which explains a lot of "it isn't working" reports: Claude's own file and web tools (Read, Edit, Write, WebFetch, WebSearch) follow permission rules instead, and hooks, local MCP servers and your status line command run with your full access.
The sandbox never turns on: 5 causes
- Linux or WSL2 is missing
bubblewraporsocat. Run/sandbox. If the panel shows only a Dependencies tab, the sandbox can't start, and the tab lists what's missing. Install them (sudo apt-get install bubblewrap socaton Ubuntu/Debian,sudo dnf install bubblewrap socaton Fedora), then restart Claude Code: the dependency check only runs at startup. A Dependencies tab next to the normal tabs means only something optional is missing, such as the seccomp filter (npm install -g @anthropic-ai/sandbox-runtime), and the sandbox can still start. Watch out: by default, if the platform doesn't support the sandbox or the startup check fails, Claude Code silently runs commands without it. Setsandbox.failIfUnavailabletotrueto make it exit instead. - Ubuntu's AppArmor restriction stops bubblewrap. You see
Ubuntu's AppArmor restriction on user namespaces stops bubblewrap here, or commands fail withbwrap: setting up uid map: Permission deniedorbwrap: loopback: Failed RTM_NEWADDR: Operation not permitted. Check withsysctl kernel.apparmor_restrict_unprivileged_userns;= 1means the restriction is on. The narrow fix is an AppArmor profile for/usr/bin/bwrap(the docs give the exact profile to write to/etc/apparmor.d/bwrap, thensudo systemctl reload apparmor). The blunt fix,sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0, lifts it for every program until you reboot. Restart Claude Code and rerun the 60-second test. - You're on WSL1 or native Windows.
Sandboxing requires WSL2means your distribution runs WSL1: check withwsl -l -vin PowerShell and upgrade it. Native Windows has no sandbox at all. Our Claude Code on Windows guide covers the native vs WSL choice. - You're inside an unprivileged container. bubblewrap can't mount a fresh
/proc, so commands fail withCan't mount proc on /newroot/proc: Operation not permitted. Setsandbox.enableWeakerNestedSandboxtotrueso the sandbox reuses the container's/proc. Only do this when the container itself is the isolation boundary you trust, because it exposes process information to sandboxed commands. /sandboxcan't save your choice.Sandbox settings are overridden by a higher-priority configuration and cannot be changed locallymeans managed settings or a--settingsflag already setsandbox.enabled,sandbox.autoAllowBashIfSandboxedorsandbox.allowUnsandboxedCommands; run/statusand read theSetting sourcesline to see which (managed settings need your administrator).Sandbox settings not changed: ... couldn't be updated (EACCES)means/sandboxcouldn't write.claude/settings.local.json: start Claude Code in a folder you can write to, fix invalid JSON in that file, or put"sandbox": {"enabled": true}in~/.claude/settings.jsoninstead. Note that/sandboxsaves to the project's local settings, so it's on only in that project until you set it in user settings. Our settings not applying guide explains the precedence.
It's on, but network commands fail: 5 causes
- The host isn't allowed. Your allowed domains start empty. In Manual and accept-edits modes you get a prompt the first time a command needs a host: Yes allows it for this session, Yes, and don't ask again saves a
WebFetch(domain:...)allow rule to local settings. IndontAskmode the connection is refused, and in auto mode it's refused unless the command listed the host and the classifier approved. WithstrictAllowlistorallowManagedDomainsOnlyon, there's no prompt in any mode. Pre-allow what your tools need, for example"sandbox": {"network": {"allowedDomains": ["registry.npmjs.org", "github.com"]}}. Tools that use the proxy see a403from it when a host isn't allowed. git pushorgit pullover SSH fails. On macOS, git over SSH fails inside the sandbox even for an allowed host, because the tunnel can't authenticate to the sandbox proxy. Switch the remote to HTTPS (git remote set-url origin https://...with a personal access token), or take git's network commands out of the sandbox with"excludedCommands": ["git fetch *", "git pull *", "git push *"]. On Linux and WSL2 it works once the host is allowed on port 22 (an entry with no port covers it), your corporate proxy permits port 22, and your key is readable as a file (adenyReadorcredentialsentry for~/.sshhides it).- A database client, plain
sshor another non-HTTP tool can't connect. Tools that ignore the proxy environment variables have no route out, even to an allowed host. You'll seeOperation not permittedorCould not resolve hoston macOS,Network is unreachableorTemporary failure in name resolutionon Linux. UDP, HTTP/3 andpingcan't leave either. Run that one command outside the sandbox with a narrowexcludedCommandsentry, ideally paired with an ask rule so you approve each run, for example"excludedCommands": ["python scripts/load_orders.py *"]plus"permissions": {"ask": ["Bash(python scripts/load_orders.py *)"]}. - A command can't reach your local dev server or a database in Docker. On macOS, set
sandbox.network.allowLocalBindingtotrue(this opens every localhost port to sandboxed commands). On Linux and WSL2 a sandboxed command'slocalhostis private to it, soallowLocalBindingdoes nothing there: useexcludedCommandsfor the command that needs the host's server. A dev hostname such asmyapp.testthat points at127.0.0.1is refused withresolved to a loopback address; add both"myapp.test:3000"and"127.0.0.1:3000"toallowedDomains. gh,gcloudorterraformfail TLS verification on macOS. Go-based CLIs can fail certificate checks under Seatbelt. Add a pattern per tool, such asgh *, toexcludedCommands, knowing it then runs with your full access and stored credentials. If you're using a MITM proxy with a custom CA viahttpProxyPort, setsandbox.enableWeakerNetworkIsolationtotrueinstead. For corporate proxies and CA bundles in general, see Claude Code proxy and SSL certificate errors.
It's on, but other tools break: 4 causes
dockerorjestfails or hangs.dockeris incompatible with the sandbox: exclude only what you need, such as"excludedCommands": ["docker compose *"].jesthangs becausewatchmandoesn't work in the sandbox: runjest --no-watchman.excludedCommandsmatching is strict: patterns useBash(...)rule syntax, so end them with*; every command in a chained call must match; acd, a redirect to a file or a$(...)substitution keeps the whole call sandboxed; and a script that callsdockerinternally doesn't match.- A write is denied inside your own project. The sandbox protects files Claude Code loads config and code from, even inside writable folders:
.claudesettings,.claude/skills,agents,commandsandhooks,.mcp.json,.git/hooksand.git/config,.vscode,.ideaand shell startup files. AnallowWriteentry doesn't override that.git mergeorgit checkouttouching one of them fails withunable to unlink old: approve Claude's offer to rerun outside the sandbox, or run it yourself in another terminal. For other tools that need a folder outside the project (~/.kube, a build cache), add it tosandbox.filesystem.allowWriterather than excluding the tool./sandbox→ Config lists the resolved paths under Denied within allowed. - "Yes, and don't ask again" won't save (Linux and WSL2). A killed session can leave 0-byte read-only placeholder files at
.claudesettings paths, so later settings writes fail. Runclaude doctor, which lists them, and delete each one withrmwhile no other Claude Code session is open in that project. - Chromium, Podman, the clipboard or
openfail. On Linux, Chromium exits withNo usable sandbox!and rootless Podman can't create user namespaces: start Chromium or Electron with--no-sandbox, exclude the test orpodmancommand, or setsandbox.allowNestedUserNamespacestotruein user settings (v2.1.305+, and it weakens the boundary). Ifpbcopy,xcliporwl-copydon't reach the clipboard, ask Claude to print the text and run/copy. On macOS,open,osascriptand browser-based sign-ins fail with error-600because Apple Events are blocked:sandbox.allowAppleEvents(user settings only) allows them but removes code-execution isolation, so excludingopen *is the safer choice.
Choosing how much it asks
In auto-allow mode (the default when you enable it in settings) sandboxed commands run without a prompt, but deny rules, content ask rules such as Bash(git push *) and rm on critical paths still go through the normal checks, and Monitor commands still prompt unless an allow rule matches them. Regular permissions mode prompts for every command even when sandboxed; set sandbox.autoAllowBashIfSandboxed to false for it. When a command fails in the sandbox, Claude may retry it unsandboxed with dangerouslyDisableSandbox, which prompts as "Bash command (unsandboxed)" in Manual mode. To forbid that escape hatch, set "allowUnsandboxedCommands": false (shown as Strict sandbox mode in /sandbox). Our free permissions builder writes the allow, ask and deny rules that go next to your sandbox block.
Facts on this page come from Anthropic's Claude Code docs on configuring the sandboxed Bash tool, the settings reference, permissions and network configuration. Behavior differs by Claude Code version; run claude update before digging. This guide isn't affiliated with Anthropic.
The sandbox limits what commands can touch; hooks can stop the risky ones before they run. Our Claude Code Power Config Pack has 6 CLAUDE.md templates, permission presets and 8 tested safety hooks, $6 with the launch code while it lasts.
Not ready to buy? Our free safety hooks block risky commands before they run.
About the author
- Free Claude Code tools and fix-it guides. solostackkits.netlify.app
Comments
Join the discussionNo comments yet. Be the first to comment.