The two sides of this change are more than 400 edits apart, too far apart to line up, so this is the differ's own diff of it and the words inside a line are not marked.
from line 1
11# Configure the sandboxed Bash tool
22
3> Learn how Claude Code's sandboxed Bash tool provides filesystem and network isolation for safer, more autonomous agent execution.
4
5The Bash sandbox lets Claude run most shell commands without stopping to ask permission. Instead of approving each command, you define which files and network domains commands can touch, and the operating system enforces that boundary for every Bash, PowerShell, or Monitor command and its child processes.
3> Restrict the files and network hosts Claude Code's shell commands can reach with the built-in sandbox. Turn it on, set the boundary, and fix what it breaks.
4
5The Bash sandbox is a boundary that the operating system enforces around the shell commands Claude runs on your machine. You set which files and network domains those commands can reach, and the limits apply to Bash, PowerShell, and Monitor commands and the processes they start. Because the operating system applies the limits while a command runs, Claude Code can [run sandboxed commands without asking you](#sandbox-modes) to approve each one.
6
7The sandbox covers shell commands only. Claude's file tools, MCP servers, and hooks [run outside it](#what-runs-outside-the-sandbox).
8
9The sandbox runs on macOS, Linux, and WSL2. On native Windows, Claude Code runs commands unsandboxed. To use the sandbox on a Windows machine, run Claude Code inside a WSL2 distribution.
610
711<Note>
8 To compare other isolation approaches such as dev containers, custom containers, and virtual machines, see [Sandbox environments](/docs/en/sandbox-environments). To reduce permission prompts for tools other than Bash, see [permission modes](/docs/en/permission-modes).
12 This page covers the sandbox around shell commands on your own machine. Other pages cover related questions:
13
14 * For how a cloud session is isolated, see [Security and isolation](/docs/en/claude-code-on-the-web#security-and-isolation)
15 * To compare other isolation approaches such as dev containers, custom containers, and virtual machines, see [Sandbox environments](/docs/en/sandbox-environments)
16 * To reduce permission prompts for tools other than Bash, see [permission modes](/docs/en/permission-modes)
917</Note>
1018
19## What the sandbox restricts
20
21While the sandbox is on, the shell commands Claude runs start inside its boundary, and so do the processes they start. The sandbox is off by default. To turn it on, run `/sandbox` in a session, as [Get started](#get-started) shows, or set [`sandbox.enabled`](/docs/en/settings-reference#sandbox-enabled) to `true` in a [settings file](/docs/en/settings) such as `~/.claude/settings.json`.
22
23The table shows what a sandboxed command can reach by default and the settings that change each default.
24
25| Access | Default | Change it with |
26| :- | :- | :- |
27| Writes | The working directory, a per-user temp directory, and [directories you've added](/docs/en/permissions#additional-directories-grant-file-access-not-configuration). [Protected paths](#protected-paths) stay write-denied | [`filesystem.allowWrite`](/docs/en/settings-reference#sandbox-filesystem-allowwrite), [`filesystem.denyWrite`](/docs/en/settings-reference#sandbox-filesystem-denywrite) |
28| Reads | Most of the machine, including credential files such as `~/.ssh` and `~/.aws/credentials` | [`filesystem.denyRead`](/docs/en/settings-reference#sandbox-filesystem-denyread), [`credentials`](#protect-credentials) |
29| Network | No direct route out. Connections go through a proxy on your machine that checks each host against your allowed domains, which start empty. Your permission mode decides [what happens to other hosts](#hosts-outside-your-allowed-domains) | [`network.allowedDomains`](/docs/en/settings-reference#sandbox-network-alloweddomains), [`network.deniedDomains`](/docs/en/settings-reference#sandbox-network-denieddomains) |
30| Environment variables | Inherited from Claude Code, including any secrets in its environment | [`credentials`](#protect-credentials), [`CLAUDE_CODE_SUBPROCESS_ENV_SCRUB`](/docs/en/env-vars) |
31
32Claude Code builds the sandbox on the open source [`@anthropic-ai/sandbox-runtime`](https://github.com/anthropics/sandbox-runtime) package.
33
34### What runs outside the sandbox
35
36The sandbox wraps shell commands. These tools and processes run outside it:
37
38* **Built-in file and web tools**: tools such as Read, Edit, Write, WebFetch, and WebSearch follow [permission rules](/docs/en/permissions) instead. A `denyRead` entry doesn't stop the Read tool, and `allowedDomains` doesn't limit WebFetch
39* **Other processes Claude Code starts**: command [hooks](/docs/en/hooks), local [MCP servers](/docs/en/mcp), [plugin monitors](/docs/en/plugins/components#monitors), [LSP servers](/docs/en/tools-reference#lsp-tool-behavior), and helper commands such as your [status line](/docs/en/statusline) command and `apiKeyHelper` run with your full access
40
41Some shell commands also run outside the sandbox, depending on your settings:
42
43* **Commands you type yourself**: a command you enter at the [`!` shell-mode prompt](/docs/en/interactive-mode#shell-mode-with-prefix) runs unsandboxed in most sessions. [Strict sandbox mode](#turn-off-the-retry-with-strict-sandbox-mode) lists the sessions where a command you type runs sandboxed
44* **Excluded commands**: commands that match [`excludedCommands`](#run-commands-outside-the-sandbox-with-excludedcommands) run unsandboxed
45* **Unsandboxed retries**: Claude can [ask to run a command unsandboxed](#the-unsandboxed-retry-escape-hatch), usually after it fails in the sandbox
46
47To put the tools, processes, and commands in this section behind one boundary, run the Claude Code process itself in a [container, virtual machine, or the sandbox runtime](/docs/en/sandbox-environments).
48
1149## Get started
1250
13The sandbox is built into Claude Code and runs on macOS, Linux, and WSL2. Native Windows is not supported. On Windows, run Claude Code inside a WSL2 distribution.
14
15On macOS, there is nothing to install: sandboxing uses the built-in Seatbelt framework. On Linux and WSL2, the sandbox relies on two packages, covered in [Set up Linux and WSL2](#set-up-linux-and-wsl2). Even if you haven't installed them yet, you can start with `/sandbox`, because its panel shows whether anything is missing.
51The sandbox is built into Claude Code. What you install depends on your platform:
52
53* **macOS**: sandboxing uses the built-in Seatbelt framework, so you can go straight to the steps
54* **Linux and WSL2**: the sandbox relies on `bubblewrap` and `socat`, covered in [Set up Linux and WSL2](#set-up-linux-and-wsl2). Even if you haven't installed them yet, you can start with `/sandbox`, because its panel shows whether anything is missing
1655
1756<Steps>
1857 <Step title="Run /sandbox">
from line 79
4079
4180 The first time a command needs a new network domain, Claude Code prompts for approval; in [auto mode](/docs/en/permission-modes#eliminate-prompts-with-auto-mode), Claude instead names the hosts a command needs [on the command itself](#per-command-allowed-domains-in-auto-mode) for the classifier to review with it.
4281
43 Commands that can't run sandboxed fall back to the regular permission flow. Claude Code titles their permission prompt "Bash command (unsandboxed)" instead of "Bash command", so you can tell which commands ran outside the sandbox. To widen or narrow what the sandbox allows, see [Configure sandboxing](#configure-sandboxing).
82 To widen or narrow what the sandbox allows, see [Configure sandboxing](#configure-sandboxing).
4483
4584 If sandboxed commands fail with `Operation not permitted` inside a container, see the Bubblewrap entry under [Troubleshooting](#troubleshooting).
4685 </Step>
from line 94
5594```
5695
5796<Warning>
58 By default, if the sandbox cannot start because dependencies are missing or the platform is unsupported, Claude Code shows a warning and runs commands without sandboxing. To make this a hard failure instead, set [`sandbox.failIfUnavailable`](/docs/en/settings-reference#sandbox-failifunavailable) to `true`. This is intended for managed deployments that require sandboxing as a security gate.
97 By default, if the sandbox can't start because a dependency is missing or the platform is unsupported, Claude Code runs commands without sandboxing. To make Claude Code exit at startup instead, set [`sandbox.failIfUnavailable`](/docs/en/settings-reference#sandbox-failifunavailable) to `true`. Managed deployments that require sandboxing as a security gate can use this setting.
5998</Warning>
6099
100### Confirm commands run inside the sandbox
101
102To check that the sandbox is working, ask Claude to run each line in the table. What you type at the [`!` prompt](#what-runs-outside-the-sandbox) usually runs outside the sandbox, so typing a line yourself doesn't test it.
103
104| Command | Result inside the sandbox |
105| :- | :- |
106| `touch ~/sandbox-probe` | Fails with `Operation not permitted` on macOS, or `Read-only file system` on Linux and WSL2 |
107| `curl --noproxy '*' https://example.com` | Fails with `Could not resolve host`, because the command has no route around the sandbox proxy |
108
109If Claude asks to retry a failed command outside the sandbox, decline the retry. If `touch` succeeds and your home directory isn't one of the directories the sandbox lets commands write to, delete `~/sandbox-probe`. Then run `/sandbox` to check that the sandbox is on and its dependencies are installed.
110
61111### Set up Linux and WSL2
62112
63On Linux and WSL2, the sandbox relies on two packages:
113On Linux and WSL2, the sandbox relies on these packages:
64114
65115* [`bubblewrap`](https://github.com/containers/bubblewrap): the unprivileged sandboxing tool that enforces filesystem isolation
66116* [`socat`](http://www.dest-unreach.org/socat/): the relay used to route network traffic through the sandbox proxy
from line 165
115165 <Accordion title="WSL2 notes">
116166 Check your WSL version with `wsl -l -v` from PowerShell. If you see `Sandboxing requires WSL2`, your distribution is running WSL1. Upgrade it to WSL2 or run Claude Code without sandboxing.
117167
118 On WSL2, WSL hands a launch of a Windows binary such as `cmd.exe`, `powershell.exe`, or anything under `/mnt/c/` to the Windows host over a Unix socket, so whether a sandboxed command can launch one follows the sandbox's [Unix-socket settings](/docs/en/settings-reference#sandbox-network-allowunixsockets): the optional seccomp filter has to be installed to block the socket in the first place. To allow these launches, set `allowAllUnixSockets`; to keep them out of the sandbox entirely, add the command to [`excludedCommands`](/docs/en/settings-reference#sandbox-excludedcommands).
168 On WSL2, WSL hands a launch of a Windows binary such as `cmd.exe`, `powershell.exe`, or anything under `/mnt/c/` to the Windows host over a Unix socket, so whether a sandboxed command can launch one follows the sandbox's [Unix-socket settings](/docs/en/settings-reference#sandbox-network-allowunixsockets): the optional seccomp filter has to be installed to block the socket in the first place. To allow these launches, set `allowAllUnixSockets`, which opens every Unix socket to sandboxed commands.
119169 </Accordion>
120170</AccordionGroup>
121171
from line 175
125175
126176#### Auto-allow mode
127177
128When a command can be sandboxed, Claude Code runs it inside the sandbox and approves it automatically, without asking your permission. Commands that cannot be sandboxed, such as those needing network access to non-allowed hosts, fall back to the regular permission flow, where Claude Code checks your [permission rules](/docs/en/permissions) and gates any command those rules do not already allow, with a prompt in Manual mode.
178Claude Code approves a command automatically, with no prompt, when the command runs inside the sandbox. A command goes through the regular [permission flow](/docs/en/permissions) when it runs outside the sandbox because it matches [`excludedCommands`](#run-commands-outside-the-sandbox-with-excludedcommands) or because Claude [retries it unsandboxed](#the-unsandboxed-retry-escape-hatch).
179
180A sandboxed command that connects to a host you haven't allowed stays in the sandbox. [Hosts outside your allowed domains](#hosts-outside-your-allowed-domains) covers who decides whether the connection goes through.
129181
130182Even in auto-allow mode, the following still apply:
131183
from line 198
146198
147199#### The unsandboxed retry escape hatch
148200
149Some commands can't run inside the sandbox at all, such as tools that are incompatible with it or that need a host you haven't allowed. Claude Code reports sandbox violations in the blocked command's result, naming the path or host the sandbox denied, so Claude sees what the sandbox blocked. Rather than failing the task or requiring you to turn sandboxing off, Claude Code includes an escape hatch: Claude analyzes the violation and may retry the command with the `dangerouslyDisableSandbox` parameter.
150
151The retried command runs outside the sandbox, so it goes through the regular permission flow. In Manual mode you get a confirmation prompt. In [auto mode](/docs/en/permission-modes#eliminate-prompts-with-auto-mode), the classifier evaluates the underlying command. While [`permissions.blockReadsOutsideWorkingDirectories`](/docs/en/settings-reference#permissions-blockreadsoutsideworkingdirectories) is on, a retry that needs approval to run outside the sandbox prompts you instead. To be prompted on every unsandboxed retry even in auto mode, add an [ask rule](/docs/en/permissions#match-by-input-parameter) for `Bash(dangerouslyDisableSandbox:true)`.
152
153You can disable this escape hatch by setting `"allowUnsandboxedCommands": false` in your [sandbox settings](/docs/en/settings-reference#sandbox-settings). With the escape hatch disabled, Claude Code ignores the `dangerouslyDisableSandbox` parameter, and every command Claude runs must run sandboxed unless you've listed it in `excludedCommands`. The `/sandbox` **Overrides** tab shows this setting as **Strict sandbox mode**.
201The unsandboxed retry is an escape hatch for commands that fail inside the sandbox, such as tools that are incompatible with it. When the sandbox blocks a network connection, Claude Code names the denied host in the command's result, so Claude sees what was blocked. Claude analyzes the failure and may retry the command with the `dangerouslyDisableSandbox` parameter.
202
203The retried command runs unsandboxed. In an interactive terminal session, who approves it depends on your permission mode:
204
205* **`bypassPermissions` mode**: the retry runs without a prompt
206* **Manual mode and `acceptEdits` mode**: you get a prompt titled "Bash command (unsandboxed)"
207* **[Auto mode](/docs/en/permission-modes#eliminate-prompts-with-auto-mode)**: a separate classifier model evaluates the underlying command
208* **`dontAsk` mode**: Claude Code denies the retry
209* **Plan mode**: see [how Claude Code gates commands while you plan](/docs/en/permission-modes#analyze-before-you-edit-with-plan-mode)
210
211These rules and settings change who approves the retry:
212
213* **A matching allow rule**: if an allow rule such as `Bash(curl *)` matches the command, it also approves the retry, so the command runs outside the sandbox with no prompt
214* **An ask rule for the parameter**: add an [ask rule](/docs/en/permissions#match-by-input-parameter) for `Bash(dangerouslyDisableSandbox:true)` to be prompted on Bash retries. You get the prompt in auto mode and `bypassPermissions` mode too, and the rule takes precedence over a matching allow rule
215* **[`permissions.blockReadsOutsideWorkingDirectories`](/docs/en/settings-reference#permissions-blockreadsoutsideworkingdirectories)**: [Actions no mode auto-approves](/docs/en/permission-modes#actions-no-mode-auto-approves) covers the retries that prompt while it's on
216
217#### Turn off the retry with strict sandbox mode
218
219You can disable the unsandboxed retry by setting `"allowUnsandboxedCommands": false` in your [sandbox settings](/docs/en/settings-reference#sandbox-settings). With the retry disabled, Claude Code ignores the `dangerouslyDisableSandbox` parameter. While the sandbox is running, commands Claude runs are then sandboxed unless they match an `excludedCommands` entry. To keep Claude Code from running commands unsandboxed when the sandbox can't start, also set [`failIfUnavailable`](/docs/en/settings-reference#sandbox-failifunavailable). The `/sandbox` **Overrides** tab shows this setting as **Strict sandbox mode**.
220
221A `false` in your user settings, `--settings`, or managed settings holds even when a project's settings set `true`. A `false` in your user settings doesn't make the sandbox admin-required, so a project's other sandbox settings still apply. Before v2.1.285, a project's `true` overrode a `false` in your user settings.
222
223If you or your administrator disable the retry in managed settings or with the `--settings` flag, the sandbox becomes admin-required. Claude Code then ignores the settings in a repository's files that loosen the sandbox, `excludedCommands` entries included. [Repository settings under an admin-required sandbox](#repository-settings-under-an-admin-required-sandbox) lists them.
154224
155225Strict sandbox mode applies to the commands Claude runs. Commands you type yourself at the [`!` shell-mode prompt](/docs/en/interactive-mode#shell-mode-with-prefix) run outside the sandbox unless the session is one of these:
156226
from line 295
225295If you placed the same configuration in `~/.claude/settings.json`, `.` would resolve to `~/.claude` instead, and project files would remain blocked by the `denyRead` rule.
226296
227297To deny sandboxed commands read access to home directories and mounted volumes while keeping the working directories readable, set [`permissions.blockReadsOutsideWorkingDirectories`](/docs/en/settings-reference#permissions-blockreadsoutsideworkingdirectories) instead of writing path rules.
298
299### Run commands outside the sandbox with `excludedCommands`
300
301List a command pattern in [`sandbox.excludedCommands`](/docs/en/settings-reference#sandbox-excludedcommands) to run matching commands outside the sandbox, which means no filesystem restrictions and no network proxy. Use it for a tool that can't work inside the sandbox and that you trust with your full access. A tool that needs one more directory or one more host may work with `allowWrite` or `allowedDomains`, which keep the command sandboxed.
302
303This example takes `docker compose` commands out of the sandbox. Save it in `~/.claude/settings.json` to apply it to all of your projects:
304
305```json theme={null}
306{
307 "sandbox": {
308 "enabled": true,
309 "excludedCommands": ["docker compose *"]
310 }
311}
312```
313
314Claude Code checks your entries against each Bash and Monitor call. A call is the whole command line Claude sends, which can chain several commands. The following rules decide whether a call leaves the sandbox:
315
316* **End the pattern with ` *`**: entries use the same syntax as a `Bash(...)` [permission rule](/docs/en/permissions#permission-rule-syntax), where a pattern with no wildcard is an exact match. `docker` matches only `docker` with no arguments. `docker *` matches `docker` with or without arguments
317* **Every command in the call has to match**: `npm ci && docker compose build` stays sandboxed unless another entry covers `npm ci`
318* **Claude Code matches the text of the call**: a script or `make` target that calls `docker` internally doesn't match, and neither does `/usr/local/bin/docker`
319* **Some calls stay sandboxed**: a redirect to a file, a `cd`, or a command substitution such as `$(...)` keeps the whole call sandboxed. The [reference entry](/docs/en/settings-reference#sandbox-excludedcommands) lists more calls that stay sandboxed
320* **Where you save the entry can matter**: while the sandbox is [admin-required](#repository-settings-under-an-admin-required-sandbox), Claude Code ignores entries in `.claude/settings.json` and `.claude/settings.local.json`
321
322An excluded command goes through the regular permission flow:
323
324* [Read-only commands](/docs/en/permissions#read-only-commands) and commands your allow rules cover run without a prompt
325* In auto mode, the classifier reviews other excluded commands
326* In `bypassPermissions` mode, an excluded command runs without a prompt unless an ask rule matches it
327
328To confirm an entry matches, switch to Manual mode and ask Claude to run a matching command that changes something, such as `docker compose up -d`. The permission prompt is titled "Bash command (unsandboxed)".
329
330<Warning>
331 An excluded command runs with your full access. A broad entry such as `docker *` covers everything that tool can do. If you write a pattern that covers an interpreter, a script inside your working directory, or a tool that acts on a file there, as `docker compose` does with its compose file, Claude can write that file and then run it outside the sandbox. A narrower pattern leaves less that Claude can run outside the sandbox.
332</Warning>
228333
229334### Disable filesystem isolation
230335
from line 582
477582 * `deny` makes the file unreadable instead
478583 * `error` stops sandbox setup until you fix the configuration
479584
480 Claude Code treats `deny` as `error` whenever the read block wouldn't be enforced: when you [disable filesystem isolation](#disable-filesystem-isolation), and when a `filesystem.allowRead` entry from any settings source re-opens the file's path.
585 Claude Code treats `deny` as `error` whenever the read block wouldn't be enforced: when you [disable filesystem isolation](#disable-filesystem-isolation), and when a `filesystem.allowRead` entry re-opens the file's path.
481586* `maskDuplicates` also replaces verbatim copies of each masked credential value, an `extract` capture or a `decode`-verified token, found outside the matched spans, for a secret repeated where matching doesn't reach. It matches raw substrings, so a short or common value would be replaced everywhere it appears; reserve it for long, high-entropy secrets. Default: false.
482587
483588`mask` applies to a single file, so list each credential file individually. Claude Code falls back to `deny` for a `mask` entry it can't mask safely: a directory path, a glob pattern, a file larger than 8 MiB, or a file that isn't UTF-8 text. Write directories as explicit `deny` entries instead; the table under [Which settings can disable it](#which-settings-can-disable-it) covers whether each form pins `filesystem.disabled` and how it behaves with filesystem isolation off.
from line 594
489594The sandboxed Bash tool restricts file system access to specific directories:
490595
491596* **Default write behavior**: read and write access to the current working directory and its subdirectories, any directories you've added with `--add-dir`, `/add-dir`, or [`permissions.additionalDirectories`](/docs/en/settings-reference#permissions-additionaldirectories), plus the per-user temp directory that `$TMPDIR` points to
492* **Default read behavior**: read access to the entire computer, except certain denied directories. Note that this default still allows reading credential files such as `~/.aws/credentials` and `~/.ssh/`. Use [`sandbox.credentials`](#protect-credentials) to block reads of these files and unset secret environment variables, or add the paths to `denyRead`.
597* **Default read behavior**: read access to the entire computer, except certain denied directories. This default still allows reading credential files, so [protect credentials](#protect-credentials) you don't want commands to read.
493598* **Read block**: with [`permissions.blockReadsOutsideWorkingDirectories`](/docs/en/settings-reference#permissions-blockreadsoutsideworkingdirectories) on, sandboxed commands also lose read access to your home directory and the other directories that hold user files, apart from the paths that [Sandboxed commands under the block](/docs/en/settings-reference#sandboxed-commands-under-the-block) lists. That section also says when this part of the block doesn't apply.
494* **Blocked access**: cannot modify files outside the working directory, added directories, and the per-user temp directory without explicit permission, including shell configuration files such as `~/.bashrc` and system binaries in `/bin/`
495599* **Git worktrees**: when the working directory is a [linked git worktree](/docs/en/worktrees), the sandbox also allows writes to the main repository's shared `.git` directory so commands such as `git commit` can update refs and the index. Writes to `hooks/` and `config` inside that directory remain denied.
496* **Configurable**: define custom allowed and denied paths through settings
497600
498601To skip filesystem isolation entirely while keeping network isolation, set [`sandbox.filesystem.disabled`](#disable-filesystem-isolation).
499602
from line 617
514617
515618### Network isolation
516619
517Network access is controlled through a proxy server running outside the sandbox:
518
519* **Domain restrictions**: Claude Code pre-allows no domains by default. The first time a command needs a new domain, Claude Code prompts for approval; in [auto mode](/docs/en/permission-modes#eliminate-prompts-with-auto-mode), Claude instead names the hosts a command needs on the command itself, per [Per-command allowed domains](#per-command-allowed-domains-in-auto-mode).
520* **Approval choices**: if you choose Yes when prompted, Claude Code allows the host for the rest of the current session and doesn't prompt again for later connections to the same host. If you choose "Yes, and don't ask again", Claude Code saves a `WebFetch(domain:...)` allow rule to your [local settings](/docs/en/permissions#permission-system), so the host stays allowed in future sessions.
620A sandboxed command has no direct route to the network:
621
622* **Linux and WSL2**: the command runs in a separate network namespace that has no connection to your network
623* **macOS**: the Seatbelt sandbox framework by default blocks connections other than the one to the sandbox proxy
624
625Claude Code runs the sandbox proxy on your machine, outside the sandbox, and directs commands to it with `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, and related environment variables. The proxy checks the hostname of each connection against your allowed and denied domains.
626
627What a tool can reach depends on whether it uses the proxy:
628
629* **Tools that read the proxy variables**: `curl`, `npm`, `git` over HTTPS, and similar tools connect once their host is allowed. An `allowedDomains` entry with no port allows every port on that host
630* **Tools that ignore the proxy variables**: plain `ssh`, most database drivers, and similar tools can't connect, even to an allowed host. See [A database client or other non-HTTP tool fails to reach an allowed host](#a-database-client-or-other-non-http-tool-fails-to-reach-an-allowed-host)
631* **Anything that isn't TCP**: UDP, HTTP/3 over QUIC, and ICMP tools such as `ping` can't leave the sandbox
632
633The following settings and behaviors control which hosts the proxy allows:
634
635* **Domain restrictions**: your allowed domains start empty. [Hosts outside your allowed domains](#hosts-outside-your-allowed-domains) covers what happens the first time a command needs a new domain.
636* **Approval choices**: if you choose Yes when prompted, Claude Code allows the host for the rest of the current session. If you choose "Yes, and don't ask again", Claude Code saves a `WebFetch(domain:...)` allow rule to your [local settings](/docs/en/permissions#permission-system), so the host stays allowed in future sessions. While the sandbox is [admin-required](#repository-settings-under-an-admin-required-sandbox), Claude Code saves the rule to your user settings, where it applies in every project.
521637* **Pre-allowed domains**: pre-allow domains with [`allowedDomains`](/docs/en/settings-reference#sandbox-network-alloweddomains) to avoid the prompt entirely. Claude Code also pre-allows domains from `WebFetch(domain:...)` allow rules, as described in [Permission rules](#permission-rules).
522* **Strict allowlist**: if you set [`strictAllowlist`](/docs/en/settings-reference#sandbox-network-strictallowlist) to `true` in user, managed, or CLI `--settings` settings, Claude Code denies sandboxed commands access to any host outside the allowlist instead of prompting. The allowlist is the same one the sandbox otherwise prompts against: `allowedDomains` plus domains from `WebFetch(domain:...)` allow rules, or only the managed settings entries when `allowManagedDomainsOnly` is set. Claude Code enforces this for sandboxed commands only; in-process tools such as `WebFetch` still follow their [permission rules](#permission-rules). Setting it in a repository's `.claude/settings.json` or `.claude/settings.local.json` has no effect. Requires Claude Code v2.1.219 or later.
638* **Strict allowlist**: if you set [`strictAllowlist`](/docs/en/settings-reference#sandbox-network-strictallowlist) to `true` in user, managed, or CLI `--settings` settings, Claude Code denies sandboxed commands access to any host outside the allowlist instead of prompting. The allowlist is `allowedDomains` plus domains from `WebFetch(domain:...)` allow rules, or only the managed settings entries when `allowManagedDomainsOnly` is set. [Locks that apply without an admin-required sandbox](#locks-that-apply-without-an-admin-required-sandbox) covers a repository's entries. Claude Code enforces this for sandboxed commands only; in-process tools such as `WebFetch` still follow their [permission rules](#permission-rules). Setting it in a repository's `.claude/settings.json` or `.claude/settings.local.json` has no effect. Requires Claude Code v2.1.219 or later.
523639* **Managed lockdown**: if [`allowManagedDomainsOnly`](/docs/en/settings-reference#sandbox-network-allowmanageddomainsonly) is set in managed settings, non-allowed domains are blocked automatically instead of prompting, and only `allowedDomains` and `WebFetch(domain:...)` allow rules from managed settings are honored.
524* **Corporate proxy**: when your network requires outbound traffic to go through a corporate proxy, set `HTTPS_PROXY`, `HTTP_PROXY`, and `NO_PROXY` as [proxy configuration](/docs/en/network-config#proxy-configuration) describes, in the `env` block of your settings so that [background agents](/docs/en/network-config#set-network-variables-in-settings-not-the-shell) get them too, or in the environment you launch Claude Code from. Claude Code enforces the domain allowlist and then tunnels allowed connections through that upstream proxy.
525* **Custom proxy support**: advanced users can implement custom rules on outgoing traffic
526* **Comprehensive coverage**: restrictions apply to all scripts, programs, and subprocesses spawned by commands
640* **Corporate proxy**: when your network requires outbound traffic to go through a corporate proxy, set `HTTPS_PROXY`, `HTTP_PROXY`, and `NO_PROXY` as [proxy configuration](/docs/en/network-config#proxy-configuration) describes, in the `env` block of your settings so that [background agents](/docs/en/network-config#set-network-variables-in-settings-not-the-shell) get them too, or in the environment you launch Claude Code from. Claude Code enforces the domain allowlist and then tunnels allowed connections through that upstream proxy. `http://` and `https://` proxy URLs work, with basic authentication in the URL if you need it.
527641
528642In a `WebFetch(domain:...)` rule, the sandbox honors two wildcard forms: a leading `*.`, such as `*.example.com`, and a bare `*`. The bare `*` form requires Claude Code v2.1.186 or later. A wildcard in any other position, such as `WebFetch(domain:example.*)`, still matches fetches but has no effect on sandboxed commands.
529643
from line 645
531645 The built-in proxy enforces the allowlist based on the requested hostname and, by default, does not terminate or inspect TLS traffic. The experimental [`network.tlsTerminate`](/docs/en/settings-reference#sandbox-network-tlsterminate) setting, available in Claude Code v2.1.199 and later, makes the built-in proxy terminate TLS itself, which [`mask` credential entries](#mask-credentials) require. See [Security limitations](#security-limitations) for the implications of the default, and [Custom proxy configuration](#custom-proxy-configuration) if your threat model requires TLS inspection.
532646</Note>
533647
648#### Hosts outside your allowed domains
649
650When a sandboxed command connects to a host that isn't in your allowed domains, the command stays in the sandbox and waits for a decision. In an interactive terminal session, the decision depends on your permission mode:
651
652| Permission mode | What happens to the connection |
653| :- | :- |
654| `bypassPermissions` mode, and plan mode with [bypass permissions available](/docs/en/permission-modes#skip-all-checks-with-bypasspermissions-mode) | Allowed without a prompt |
655| Manual mode, `acceptEdits` mode, and plan mode otherwise | You get a prompt |
656| Auto mode | Refused unless the command [listed the host](#per-command-allowed-domains-in-auto-mode) and the classifier approved the list |
657| `dontAsk` mode | Refused |
658
659With [`strictAllowlist`](/docs/en/settings-reference#sandbox-network-strictallowlist) or [`allowManagedDomainsOnly`](/docs/en/settings-reference#sandbox-network-allowmanageddomainsonly) on, the built-in sandbox proxy refuses the connection in every permission mode. In `bypassPermissions` mode, hosts outside your allowed domains are allowed unless one of them is on. [The unsandboxed retry escape hatch](#the-unsandboxed-retry-escape-hatch) covers when a command can leave the sandbox in that mode. A connection to a host in [`deniedDomains`](/docs/en/settings-reference#sandbox-network-denieddomains) is refused in every permission mode too.
660
661#### Hostnames that resolve to local addresses
662
663After a hostname passes the allowlist, the sandbox proxy resolves it and refuses the connection when the name resolves only to local addresses. Local addresses include loopback addresses such as `127.0.0.1`, link-local addresses such as the `169.254.169.254` cloud metadata endpoint, and addresses assigned to your own machine. The names `localhost` and `*.localhost` are allowed to resolve to loopback.
664
665An allowed intranet hostname that resolves to a private range such as `10.0.0.0/8` connects. To let a name resolve to a refused address, add that IP address to `allowedDomains`, such as `"127.0.0.1:8080"`.
666
667The check applies to hostnames. Your allowed domains and permission mode decide a connection to an IP address. The proxy also skips the check for connections it sends through an upstream corporate proxy, because that proxy resolves the name.
668
534669#### Per-command allowed domains in auto mode
535670
536671In [auto mode](/docs/en/permission-modes#eliminate-prompts-with-auto-mode) with sandboxing on, Claude names the hosts a command needs on the command itself instead of triggering a network approval for each connection. Each Bash, PowerShell, or [Monitor](/docs/en/tools-reference#monitor-tool) command that runs in the sandbox can carry a list of hosts beyond the sandbox's allowlist: a domain such as `registry.npmjs.org`, a wildcard such as `*.pythonhosted.org`, or an IP address, each with an optional `:port`. The classifier reviews the hosts together with the command. Requires Claude Code v2.1.271 or later.
from line 701
566701
567702WSL1 is not supported because bubblewrap requires kernel features only available in WSL2.
568703
569These same primitives are available as the standalone [`@anthropic-ai/sandbox-runtime`](https://github.com/anthropic-experimental/sandbox-runtime) package, which the [Sandbox environments](/docs/en/sandbox-environments#sandbox-runtime) page covers as a separate approach for wrapping the entire Claude Code process.
704You can also run the [`@anthropic-ai/sandbox-runtime`](https://github.com/anthropics/sandbox-runtime) package on its own to wrap the Claude Code process. See [Sandbox runtime](/docs/en/sandbox-environments#sandbox-runtime).
570705
571706## How sandboxing relates to permissions and permission modes
572707
from line 754
619754
620755To require the sandbox for every developer, deliver the `sandbox` keys through [managed settings](/docs/en/managed-settings#delivery-mechanisms), either as a file managed by your MDM or through [server-managed settings](/docs/en/server-managed-settings) on claude.ai.
621756
622The following managed settings configuration enables the sandbox, refuses to start Claude Code if the sandbox cannot initialize, and prevents the model from retrying commands outside the sandbox:
757The following managed settings configuration enables the sandbox, refuses to start Claude Code when the platform is unsupported or a dependency is missing, and prevents the model from retrying commands outside the sandbox:
623758
624759```json theme={null}
625760{
from line 768
633768
634769The two keys beyond `enabled` control what happens when the sandbox cannot run a command:
635770
636* **`failIfUnavailable`**: a missing dependency such as bubblewrap on Linux blocks Claude Code from starting rather than showing a warning and falling back to unsandboxed execution
771* **`failIfUnavailable`**: a missing dependency such as bubblewrap on Linux blocks Claude Code from starting rather than falling back to unsandboxed execution
637772* **`allowUnsandboxedCommands: false`**: Claude Code ignores the `dangerouslyDisableSandbox` escape hatch, so when a command fails under the sandbox, Claude can't retry it unsandboxed
638773
639Two additions are worth considering alongside them. Add `excludedCommands` for any organization-approved tools that must run without isolation. Add [`sandbox.credentials`](#protect-credentials) entries for credential directories such as `~/.aws` and `~/.ssh` and for secret environment variables, since the default read policy still allows them.
640
641This configuration sandboxes the commands Claude runs. A developer can still type a command at the [`!` shell-mode prompt](/docs/en/interactive-mode#shell-mode-with-prefix) and run it outside the sandbox, with the same access they already have in any terminal outside Claude Code. See [The unsandboxed retry escape hatch](#the-unsandboxed-retry-escape-hatch) for the sessions where typed commands run sandboxed.
642
643The sandbox does not run on native Windows, so if your fleet includes Windows hosts, scope this configuration to macOS and Linux or have those users run Claude Code inside WSL2 or a container.
774Consider these additions alongside them:
775
776* Add `excludedCommands` for any organization-approved tools that must run without isolation, because this configuration [stops a repository's settings from taking commands out of the sandbox](#repository-settings-under-an-admin-required-sandbox)
777* Add [`sandbox.credentials`](#protect-credentials) entries for credential directories such as `~/.aws` and `~/.ssh` and for secret environment variables, since the default read policy still allows them
778
779This configuration sandboxes the commands Claude runs. A developer can still type a command at the [`!` shell-mode prompt](/docs/en/interactive-mode#shell-mode-with-prefix) and run it outside the sandbox, with the same access they already have in any terminal outside Claude Code. See [strict sandbox mode](#turn-off-the-retry-with-strict-sandbox-mode) for the sessions where typed commands run sandboxed.
780
781The sandbox doesn't run on native Windows, so with `failIfUnavailable` set, Claude Code exits at startup on those machines. If your fleet includes Windows hosts, you can:
782
783* **Deliver the configuration by operating system**: deploy it through your MDM or as a [managed settings file](/docs/en/managed-settings#delivery-mechanisms) on macOS and Linux machines only. [Server-managed settings](/docs/en/server-managed-settings#current-limitations) apply to all users in the organization
784* **Move Windows users into a supported environment**: have them run Claude Code inside WSL2 or a container
644785
645786### Keep developers from widening the policy
646787
647For boolean keys such as `enabled` and `failIfUnavailable`, Claude Code uses the managed value and ignores anything a developer sets locally. For array keys such as `excludedCommands` and `allowRead`, Claude Code merges entries from every scope the session loads, so a developer can append entries that widen the policy.
648
649Set `allowManagedReadPathsOnly` to `true` in managed settings so that only `allowRead` entries from managed settings are honored. This prevents developers from widening read access beyond the organization-approved paths. To lock network domains to the managed values the same way, set [`allowManagedDomainsOnly`](/docs/en/settings-reference#sandbox-network-allowmanageddomainsonly).
788When managed settings set a Boolean key such as `enabled` or `failIfUnavailable`, Claude Code uses the managed value and ignores anything a developer sets locally. For array keys such as `allowRead`, Claude Code merges entries from the scopes the session loads, so a developer can append entries that widen the policy unless a lock covers that key.
789
790Unless managed settings set them, a developer's user settings or `--settings` can turn on the following keys. A repository's `.claude/settings.json` can too, unless the sandbox is [admin-required](#repository-settings-under-an-admin-required-sandbox). Each one weakens the sandbox, so set it to `false` in managed settings if you don't want it used:
791
792* [`enableWeakerNestedSandbox`](/docs/en/settings-reference#sandbox-enableweakernestedsandbox)
793* [`enableWeakerNetworkIsolation`](/docs/en/settings-reference#sandbox-enableweakernetworkisolation)
794* [`network.allowAllUnixSockets`](/docs/en/settings-reference#sandbox-network-allowallunixsockets)
795* [`network.allowLocalBinding`](/docs/en/settings-reference#sandbox-network-allowlocalbinding)
796* [`allowAppleEvents`](/docs/en/settings-reference#sandbox-allowappleevents), which a repository can't turn on
797
798Set `allowManagedReadPathsOnly` to `true` in managed settings so that only `allowRead` entries from managed settings are honored. This prevents developers from widening read access beyond the organization-approved paths.
799
800To lock network domains to the managed values the same way, set [`allowManagedDomainsOnly`](/docs/en/settings-reference#sandbox-network-allowmanageddomainsonly). With the lock on, only managed settings can set a [proxy port](#custom-proxy-configuration).
650801
651802When managed settings configure `sandbox.filesystem` or list any `sandbox.credentials.files` entry with `"mode": "deny"`, only managed settings can set [`filesystem.disabled`](#disable-filesystem-isolation), so developers can't switch off administrator-deployed filesystem restrictions. Whether a `mask` entry pins the key depends on how it resolves; the table under [Which settings can disable it](#which-settings-can-disable-it) covers the four cases.
652803
653`excludedCommands` has no equivalent managed-only lockdown, so a developer can always append entries that run additional commands outside the sandbox. Keep the managed list narrow.
804#### Repository settings under an admin-required sandbox
805
806The sandbox is admin-required while one of these settings is in effect:
807
808* [`allowUnsandboxedCommands`](/docs/en/settings-reference#sandbox-allowunsandboxedcommands) set to `false` in managed settings, or with the `--settings` flag unless managed settings set it to `true`
809* [`allowManagedDomainsOnly`](/docs/en/settings-reference#sandbox-network-allowmanageddomainsonly) set to `true` in managed settings
810
811These settings don't turn the sandbox on, so set `enabled` as well.
812
813While the sandbox is admin-required, Claude Code takes the settings that loosen it only from managed settings, the `--settings` flag, and each developer's `~/.claude/settings.json`. It ignores these settings in a repository's `.claude/settings.json` and `.claude/settings.local.json`:
814
815| Repository setting | What Claude Code ignores |
816| :- | :- |
817| `excludedCommands`, `ignoreViolations`, `network.allowedDomains`, `network.allowUnixSockets`, `network.allowMachLookup`, `network.httpProxyPort`, `network.socksProxyPort` | Every entry |
818| `filesystem.allowWrite`, `Edit(...)` allow rules, `permissions.additionalDirectories` | The write access each entry gives sandboxed commands. Claude's file tools still follow the `Edit(...)` rules and additional directories |
819| `WebFetch(domain:...)` allow rules | The host each rule adds to the sandbox allowlist. The WebFetch tool still follows the rule |
820| `enableWeakerNestedSandbox`, `enableWeakerNetworkIsolation`, `network.allowAllUnixSockets`, `network.allowLocalBinding` | `true`. A `false` still applies |
821| `enabled`, `failIfUnavailable` | `false`, when the developer's `~/.claude/settings.json` sets `true` |
822| `filesystem.allowRead` | An entry at or under a path that managed settings, `--settings`, or user settings deny reading, or a glob that could match one |
823
824These settings still apply while the sandbox is admin-required:
825
826* **In a repository's files**: deny entries and the `autoAllowBashIfSandboxed` value. Set the key in managed settings to keep a repository from changing it
827* **In a developer's own settings**: the settings in the table still apply from `~/.claude/settings.json` or `--settings`, unless a managed-only lock such as `allowManagedDomainsOnly` covers them. Most of them, such as `excludedCommands` and `filesystem.allowWrite`, have no managed-only lock
828
829The configuration under [Enforce sandboxing with managed settings](#enforce-sandboxing-with-managed-settings) makes the sandbox admin-required. Add the `excludedCommands`, `allowWrite`, and socket entries that your approved tools need to managed settings, because a repository can't supply them.
830
831Requires Claude Code v2.1.285 or later. From v2.1.282 to v2.1.284, the same settings made Claude Code ignore a repository's `excludedCommands` entries.
832
833#### Locks that apply without an admin-required sandbox
834
835Some settings make Claude Code ignore the repository keys that directly override one restriction, even when the sandbox isn't admin-required. Each one has this effect only when you set it in a file its row names, and the repository's other sandbox settings still apply. Requires Claude Code v2.1.285 or later.
836
837| Setting | Where you set it | What Claude Code ignores in a repository's settings |
838| :- | :- | :- |
839| `network.deniedDomains` or a `WebFetch(domain:...)` deny rule | Managed settings, `--settings` | `httpProxyPort` and `socksProxyPort` |
840| `network.strictAllowlist` | Managed settings, `--settings`, user settings | The proxy ports, `allowedDomains`, and `WebFetch(domain:...)` allow rules |
841| `filesystem.denyRead`, a `Read(...)` deny rule, or a `credentials.files` entry | Managed settings, `--settings` | An `allowRead`, `allowWrite`, `Edit(...)` allow, or `additionalDirectories` entry at or under a path that managed settings, `--settings`, or user settings deny reading, or a glob that could match one |
842
843These locks change what sandboxed commands can reach. The WebFetch tool and Claude's file tools still follow a repository's rules and additional directories.
654844
655845### Custom proxy configuration
656846
657For organizations requiring advanced network security, you can implement a custom proxy to:
658
659* Decrypt and inspect HTTPS traffic
660* Apply custom filtering rules
661* Log all network requests
662* Integrate with existing security infrastructure
663
664To point Claude Code at your proxy, set the proxy ports in [sandbox settings](/docs/en/settings-reference#sandbox-settings):
847To inspect, filter, or log sandbox traffic with your own tooling, replace the built-in sandbox proxy with a proxy you run on the same machine.
848
849To route sandbox traffic through a corporate proxy elsewhere on your network, set `HTTPS_PROXY` instead, as the **Corporate proxy** entry under [Network isolation](#network-isolation) describes. That way, Claude Code's allowlist still applies.
850
851To direct sandboxed commands to your proxy, set the localhost ports it listens on in [sandbox settings](/docs/en/settings-reference#sandbox-settings):
665852
666853```json theme={null}
667854{
from line 861
674861}
675862```
676863
864If you set a port and also set `HTTPS_PROXY` or `HTTP_PROXY`, Claude Code doesn't forward what sandboxed commands send to your proxy on to the proxy those variables name. To reach a corporate proxy, configure your own proxy to forward to it.
865
866Which files can set a port depends on your other sandbox settings:
867
868* **`allowManagedDomainsOnly` is on**: managed settings only
869* **The sandbox is [admin-required](#repository-settings-under-an-admin-required-sandbox), or a [narrower network lock](#locks-that-apply-without-an-admin-required-sandbox) applies**: managed settings, `--settings`, and user settings
870* **Otherwise**: any settings file
871
872Claude Code ignores a port set anywhere else. Before v2.1.285, any settings file could set a port.
873
874<Warning>
875 Once either port applies, your proxy is responsible for filtering everything sent to it. Claude Code's own network controls, such as `allowedDomains`, `deniedDomains`, `strictAllowlist`, approval prompts, and the [local-address check](#hostnames-that-resolve-to-local-addresses), stop applying to that traffic. A sandboxed command can connect to either proxy, so if you set only one port, Claude Code's domain lists on the other proxy don't limit what the command reaches through yours.
876</Warning>
877
677878## Troubleshooting
678879
679Some commands fail inside the sandbox even though they work outside it. The fixes below cover the most common cases.
680
681* **Commands fail with a host-not-allowed error**: many CLI tools need to reach specific hosts. Granting permission when prompted adds the host to your allowed list so the tool runs inside the sandbox in future.
880Some commands fail inside the sandbox even though they work outside it. The following list covers short fixes. Failures that need a longer explanation each have their own heading.
881
882If your organization's sandbox is [admin-required](#repository-settings-under-an-admin-required-sandbox), Claude Code ignores the settings these fixes name in a project's settings files, so save them in `~/.claude/settings.json`, where they apply in every project. If a fix still has no effect, your organization's managed settings may set that key.
883
884A fix that adds an `excludedCommands` pattern removes the sandbox from the commands the pattern matches. See [what an excluded command can do](#run-commands-outside-the-sandbox-with-excludedcommands).
885
886* **Commands fail with a host-not-allowed error**: many CLI tools need to reach specific hosts. Approve the host when prompted, or add it to [`allowedDomains`](/docs/en/settings-reference#sandbox-network-alloweddomains). If your organization locks the allowlist with `allowManagedDomainsOnly`, there's no prompt, so ask your administrator to add the host.
682887* **`jest` hangs or fails**: `watchman` is incompatible with the sandbox. Run `jest --no-watchman` instead.
683* **Go-based CLIs fail TLS verification on macOS**: tools such as `gh`, `gcloud`, and `terraform` may fail TLS verification under Seatbelt. List these tools in [`excludedCommands`](/docs/en/settings-reference#sandbox-excludedcommands). If you are using `httpProxyPort` with a MITM proxy and custom CA, set [`enableWeakerNetworkIsolation`](/docs/en/settings-reference#sandbox-enableweakernetworkisolation) to `true` instead.
684* **`open`, `osascript`, or browser-based auth flows fail with error `-600` on macOS**: the sandbox blocks Apple Events by default. Set [`allowAppleEvents`](/docs/en/settings-reference#sandbox-allowappleevents) to `true` in your user, managed, or CLI settings to allow them. Project settings are ignored for this key. Enabling it removes code-execution isolation, since sandboxed commands can then launch other applications unsandboxed with no user prompt and send AppleScript commands to running applications, subject to the macOS automation-consent prompt (TCC). Alternatively, add the command to [`excludedCommands`](/docs/en/settings-reference#sandbox-excludedcommands).
685* **`docker` commands fail**: `docker` is incompatible with the sandbox. Add `docker *` to [`excludedCommands`](/docs/en/settings-reference#sandbox-excludedcommands).
888* **Go-based CLIs fail TLS verification on macOS**: tools such as `gh`, `gcloud`, and `terraform` may fail TLS verification under Seatbelt. Add a pattern for each tool, such as `gh *`, to [`excludedCommands`](#run-commands-outside-the-sandbox-with-excludedcommands). The tool then runs with your full access and its stored credentials. If you are using `httpProxyPort` with a MITM proxy and custom CA, set [`enableWeakerNetworkIsolation`](/docs/en/settings-reference#sandbox-enableweakernetworkisolation) to `true` instead.
889* **`open`, `osascript`, or browser-based auth flows fail with error `-600` on macOS**: the sandbox blocks Apple Events by default. Set [`allowAppleEvents`](/docs/en/settings-reference#sandbox-allowappleevents) to `true` in your user, managed, or CLI settings to allow them. Project settings are ignored for this key. Enabling it removes code-execution isolation, since sandboxed commands can then launch other applications unsandboxed with no user prompt and send AppleScript commands to running applications, subject to the macOS automation-consent prompt (TCC). Alternatively, add a pattern such as `open *` to [`excludedCommands`](#run-commands-outside-the-sandbox-with-excludedcommands). Each `open` call then goes through the permission flow, and `open` can launch any file or app, including one Claude wrote.
890* **`docker` commands fail**: `docker` is incompatible with the sandbox. Take the `docker` commands you need out of the sandbox with an [`excludedCommands`](#run-commands-outside-the-sandbox-with-excludedcommands) pattern such as `docker compose *`. That section explains what an excluded `docker` command can reach. A narrower pattern takes fewer commands out of the sandbox.
686891* **`pbcopy`, `xclip`, or `wl-copy` doesn't update the clipboard**: these clipboard utilities can fail to reach the system clipboard from inside the sandbox, in which case the text piped to them doesn't arrive.
687892
688893 To put Claude's output on your clipboard, ask Claude to print it in its response, then run [`/copy`](/docs/en/commands). `/copy` writes to the clipboard from the Claude Code process rather than from a sandboxed command.
from line 895
690895 When Claude pipes text to one of these tools, adding the tool to [`excludedCommands`](/docs/en/settings-reference#sandbox-excludedcommands) doesn't take that call out of the sandbox on its own.
691896* **A git command fails with `unable to unlink old`**: `git merge`, `git checkout`, and similar commands fail this way when they need to replace a file the sandbox denies writes to, whether that file is under a [protected path](#protected-paths) such as `.claude/skills`, under one of your `denyWrite` entries, or outside the directories the sandbox lets commands write to at all. On Linux and WSL2 the error ends with `Read-only file system`.
692897
693 After the failure, Claude may [offer to rerun the command outside the sandbox](#the-unsandboxed-retry-escape-hatch); approve that retry, or run the git command yourself in another terminal. If you've set `allowUnsandboxedCommands` to `false`, Claude can't offer the retry, so run the command yourself. If the same git command fails often, add it to [`excludedCommands`](/docs/en/settings-reference#sandbox-excludedcommands).
898 After the failure, Claude may [offer to rerun the command outside the sandbox](#the-unsandboxed-retry-escape-hatch); approve that retry, or run the git command yourself in another terminal. If you've set `allowUnsandboxedCommands` to `false`, Claude can't offer the retry, so run the command yourself.
694899* **Bubblewrap fails to start inside a container**: in an unprivileged container, bubblewrap can't mount a fresh `/proc` filesystem, so sandboxed commands fail with a `bwrap` error such as `Can't mount proc on /newroot/proc: Operation not permitted`. Set [`enableWeakerNestedSandbox`](/docs/en/settings-reference#sandbox-enableweakernestedsandbox) to `true` so the inner sandbox bind-mounts the container's existing `/proc` instead. Only use this setting when the outer container already provides the isolation boundary you need, since it exposes process information to sandboxed commands that a fresh `/proc` mount would hide.
695900* **0-byte read-only files appear at `.claude` settings paths, and "Yes, and don't ask again" doesn't save**: on Linux and WSL2, the sandbox holds a write denial on a file that doesn't exist yet by creating a 0-byte read-only placeholder there while a sandboxed command runs. The sandbox removes the placeholder afterward. If a session is killed before that cleanup runs, for example by SIGKILL, the placeholders stay behind. Later sessions bind them read-only again on every start, so a settings write such as saving a permission choice fails where one sits.
696901
697902 Run `claude doctor` to list the leftover placeholder files. The [`Stale sandbox mask files left by a killed session`](/docs/en/errors#stale-sandbox-mask-files-left-by-a-killed-session) warning names up to three of them and counts the rest. Delete each file with `rm` while no other Claude Code session is running in that project. Before v2.1.257, Claude Code left the same placeholders behind without flagging them.
698903* **`--dangerously-skip-permissions` fails as root**: this flag is blocked when running as root or via sudo on Linux and macOS, because root access combined with no permission prompts can modify any file or service on the system. The check is skipped automatically inside a recognized sandbox. To run autonomously in a container, use the [dev container](/docs/en/devcontainer) configuration, which runs Claude Code as a non-root user.
904
905### `git` over SSH fails with the sandbox on
906
907On macOS, `git fetch`, `git pull`, and `git push` against an SSH remote fail inside the sandbox even when the host is allowed. On Linux and WSL2, they work once the host is allowed. Claude Code tunnels git's SSH connection through the [sandbox proxy](#network-isolation), and the macOS tunnel can't authenticate to that proxy.
908
909On Linux and WSL2, check these if the connection still fails:
910
911* **The host is allowed on port 22**: an `allowedDomains` entry with no port, such as `"git.example.com"`, covers it
912* **Your corporate proxy permits port 22**: if your network requires an upstream proxy, the tunnel goes through it too
913* **The key is readable as a file**: the sandbox can block the `ssh-agent` socket, and a `denyRead` or `credentials` entry for `~/.ssh` hides your key files
914
915On macOS, switch the remote to HTTPS, which needs HTTPS credentials such as a personal access token:
916
917```bash theme={null}
918git remote set-url origin https://git.example.com/example-org/example-repo.git
919```
920
921If you have to keep the SSH remote, take git's network commands out of the sandbox with [`excludedCommands`](#run-commands-outside-the-sandbox-with-excludedcommands):
922
923```json theme={null}
924{
925 "sandbox": {
926 "excludedCommands": ["git fetch *", "git pull *", "git push *"]
927 }
928}
929```
930
931These entries match `git push origin main`. A call that adds a `cd`, uses `git -C`, or contains a command substitution stays sandboxed. The excluded git commands can reach any host, not only the ones in `allowedDomains`.
932
933Plain `ssh`, `scp`, and `rsync` over SSH fail for the reason [the database client entry](#a-database-client-or-other-non-http-tool-fails-to-reach-an-allowed-host) gives.
934
935### A database client or other non-HTTP tool fails to reach an allowed host
936
937A tool that ignores the proxy environment variables can't connect from inside the sandbox, even to a host in `allowedDomains`. A sandboxed command has [no direct route to the network](#network-isolation), so a tool that opens its own connection fails. Most database drivers, plain `ssh`, and tools that use UDP behave this way.
938
939The failure looks like a network or name resolution error:
940
941* **macOS**: `Operation not permitted`, or a name resolution error such as `Could not resolve host`
942* **Linux and WSL2**: `Network is unreachable`, or a name resolution error such as `Temporary failure in name resolution`
943
944A tool that uses the proxy fails differently when its host isn't allowed. You get a network prompt, or the tool receives a `403` response from the proxy.
945
946To let the tool connect, run the command that needs it outside the sandbox with [`excludedCommands`](#run-commands-outside-the-sandbox-with-excludedcommands). This example excludes one script and adds an [ask rule](/docs/en/permissions) so that you approve each run:
947
948```json theme={null}
949{
950 "sandbox": {
951 "excludedCommands": ["python scripts/load_orders.py *"]
952 },
953 "permissions": {
954 "ask": ["Bash(python scripts/load_orders.py *)"]
955 }
956}
957```
958
959The script runs with your full access, and Claude can edit a script that's inside your working directory, so review it when the prompt appears.
960
961### A command fails to reach a server on localhost
962
963By default, a sandboxed command can't connect directly to a server that's running on your machine outside the sandbox, such as a dev server or a database in a container. What you can change depends on your platform:
964
965* **macOS**: set [`network.allowLocalBinding`](/docs/en/settings-reference#sandbox-network-allowlocalbinding) to `true`. Sandboxed commands can then listen on network ports and connect to any port on localhost, which includes every other service listening there. A localhost service that doesn't require authentication, such as a debugger, can then act for the command outside the sandbox, and a command that listens on a non-loopback address accepts connections from other machines
966* **Linux and WSL2**: a sandboxed command's `localhost` is private to that command. The command can listen on a port and reach servers it started itself. A direct connection to `localhost` or `127.0.0.1` doesn't reach servers on the host, and `allowLocalBinding` has no effect. Run the command that needs the host's server outside the sandbox with [`excludedCommands`](#run-commands-outside-the-sandbox-with-excludedcommands), where it has no filesystem or network limits. For connections that go through the sandbox proxy, see [Hostnames that resolve to local addresses](#hostnames-that-resolve-to-local-addresses)
967
968This example turns the setting on for macOS:
969
970```json theme={null}
971{
972 "sandbox": {
973 "network": {
974 "allowLocalBinding": true
975 }
976 }
977}
978```
979
980An `allowedDomains` entry for `localhost` applies to connections that go through the proxy, so it doesn't change a direct connection. Claude Code sets `NO_PROXY` for sandboxed commands so that they connect to `localhost` directly instead of through the proxy. The entry also exposes every port on your machine's localhost to a command that does use the proxy. For a development hostname that points at `127.0.0.1`, see [An allowed hostname is refused with `resolved to a loopback address`](#an-allowed-hostname-is-refused-with-resolved-to-a-loopback-address).
981
982### An allowed hostname is refused with `resolved to a loopback address`
983
984The sandbox proxy refuses an allowed hostname that [resolves to a local address](#hostnames-that-resolve-to-local-addresses), which affects development names such as `myapp.test` that point at `127.0.0.1`. The command sees a `403` response whose body names the kind of address, such as `Connection to myapp.test blocked: resolved to a loopback address`.
985
986Add the IP address the name resolves to alongside the hostname in `allowedDomains`, each with the port your server listens on:
987
988```json theme={null}
989{
990 "sandbox": {
991 "network": {
992 "allowedDomains": ["myapp.test:3000", "127.0.0.1:3000"]
993 }
994 }
995}
996```
997
998An IP address entry with no port lets sandboxed commands reach every service listening on that address.
999
1000Before v2.1.284, the proxy connected to whatever address an allowed hostname resolved to.
1001
1002### `/sandbox` fails with `Sandbox settings are overridden by a higher-priority configuration`
1003
1004`/sandbox` prints `Error: Sandbox settings are overridden by a higher-priority configuration and cannot be changed locally.` instead of opening its panel when a higher [settings level](/docs/en/settings#settings-precedence) sets `sandbox.enabled`, `sandbox.autoAllowBashIfSandboxed`, or `sandbox.allowUnsandboxedCommands`. The panel saves your choices to `.claude/settings.local.json`, and a value saved there can't override those levels.
1005
1006Managed settings and `--settings` rank above local settings. To see which of them this session loaded, run `/status` and read the `Setting sources` line:
1007
1008* **`Command line arguments`**: if you started Claude Code with [`--settings`](/docs/en/settings#change-a-setting-for-one-session), check whether the file or JSON you passed sets one of those keys. If it does, change the value there, or start Claude Code again without those keys.
1009* **`Enterprise managed settings`**: your organization's managed settings are loaded. If they set one of those keys, you can't change that key from `/sandbox` or from any settings file you control, so ask your administrator.
6991010
7001011## Limitations
7011012
from line 1022
7111022
7121023* **Privilege escalation via Unix sockets**: the `allowUnixSockets` configuration can inadvertently grant access to system services that could lead to sandbox bypasses. For example, allowing access to `/var/run/docker.sock` effectively grants access to the host system through the Docker socket. Consider carefully any Unix sockets that you allow through the sandbox.
7131024* **Filesystem permission escalation**: overly broad filesystem write permissions can enable privilege escalation attacks. Allowing writes to directories containing executables in `$PATH`, system configuration directories, or user shell configuration files such as `.bashrc` or `.zshrc` can lead to code execution in different security contexts when other users or system processes access these files.
714* **Linux sandbox strength**: the Linux implementation provides strong filesystem and network isolation but includes an `enableWeakerNestedSandbox` mode that enables it to work inside Docker environments without privileged namespaces, or on Linux hosts where unprivileged user namespaces are disabled by sysctl. This option considerably weakens security and should only be used when additional isolation is otherwise enforced.
1025* **Linux sandbox strength**: the Linux implementation provides strong filesystem and network isolation but includes an `enableWeakerNestedSandbox` mode that enables it to work inside Docker environments without privileged namespaces. This option considerably weakens security and should only be used when additional isolation is otherwise enforced.
7151026* **Apple Events on macOS**: the macOS sandbox blocks Apple Events by default. The `allowAppleEvents` setting lifts this restriction so tools such as `open` and `osascript` work, but it removes code-execution isolation: sandboxed commands can launch other applications unsandboxed with no user prompt, and can send AppleScript commands to running applications, subject to the per-app macOS automation-consent prompt (TCC). It is only honored from user, managed, or CLI settings. Project settings cannot enable it.
7161027
7171028### Platform and tool compatibility
from line 1033
7221033
7231034### Scope
7241035
725The sandbox isolates Bash subprocesses. Other tools operate under different boundaries:
726
727* **Built-in file tools**: Read, Edit, and Write use the permission system directly rather than running through the sandbox. See [permissions](/docs/en/permissions).
1036The sandbox isolates shell commands and their child processes. [What runs outside the sandbox](#what-runs-outside-the-sandbox) lists the tools and helper processes it doesn't cover. Computer use and subagents relate to the sandbox as follows:
1037
7281038* **Computer use**: when Claude opens apps and controls your screen, it runs on your actual desktop rather than in an isolated environment. Per-app permission prompts gate each application. See [computer use in the CLI](/docs/en/computer-use) or [computer use in Desktop](/docs/en/desktop#let-claude-use-your-computer).
729* **Environment variables**: sandboxed Bash commands inherit the parent process environment by default, including any credentials set there. Use [`sandbox.credentials`](#protect-credentials) to unset or mask specific variables for sandboxed commands, or set [`CLAUDE_CODE_SUBPROCESS_ENV_SCRUB`](/docs/en/env-vars) to strip credentials from all subprocesses.
7301039* **Subagents**: [subagents](/docs/en/sub-agents) run in the same process as the parent session and use the same sandbox configuration. Bash commands inside a subagent are sandboxed when sandboxing is enabled in the parent session.
7311040* **Mods**: a [mod](/docs/en/plugins/mods/overview) is a plugin that runs its own code inside Claude Code, and a process that a mod starts runs outside the sandbox. See [What a mod can reach](/docs/en/plugins/mods/overview#what-a-mod-can-reach).
7321041
7331042
No line in this hunk matches that.