Sandbox and isolation
This page answers the sandbox question for the extracted cli.js: does Claude Code have a sandbox, and how is it designed?
Yes. The bundle contains a source-confirmed command sandbox subsystem. It is settings- and policy-driven, wraps shell commands before execution, supports Linux/WSL and macOS differently, exposes network and filesystem restrictions, and can ask for permission or fall back outside the sandbox depending on policy.
Source anchors
| Semantic alias | Source | Approximate location | String or symbol | Meaning |
|---|---|---|---|---|
| SandboxViolationMetadata | cli.js | line ~53 | hadSandboxViolation | Shell failures can carry sandbox-violation metadata. |
| SandboxStartupProfiler | cli.js | line ~64 | sandbox_init, before_sandbox_init, after_sandbox_init | Startup profiling treats sandbox init as an explicit phase. |
| SandboxWriteAllowlist | cli.js | line ~185, byte 0x10a185 | allowWrite:y.array | Filesystem write allowlist setting. |
| SandboxFailIfUnavailable | cli.js | line ~185, byte 0x10a4df | failIfUnavailable:y.boolean | Startup can hard-fail if sandbox is required but unavailable. |
| UnsandboxedCommandPolicy | cli.js | line ~185, byte 0x10a663 | allowUnsandboxedCommands:y.boolean | Policy knob controlling whether dangerouslyDisableSandbox can bypass isolation. |
| BubblewrapPathPolicy | cli.js | line ~185, byte 0x10aa5d | bwrapPath | Linux/WSL bubblewrap binary override from managed settings. |
| SocatPathPolicy | cli.js | line ~185, byte 0x10ab72 | socatPath | Linux/WSL socat override for sandbox network proxy. |
| SandboxManagedPolicyMerge | cli.js | line ~187 | sandbox.enabled, sandbox.failIfUnavailable, sandbox.network, sandbox.filesystem | Managed settings merge preserves sandbox policy controls. |
| SandboxSettingsValidator | cli.js | line ~188 | enabled, failIfUnavailable, allowUnsandboxedCommands, network, filesystem, ignoreViolations | Settings-key validator recognizes sandbox settings. |
| SandboxRuntimePackageLookup | cli.js | line ~748 | @anthropic-ai/sandbox-runtime | Runtime searches for the external sandbox-runtime package. |
| LinuxSandboxDependencyChecks | cli.js | line ~748 | bubblewrap (bwrap) not installed, socat not installed | Linux dependency checks. |
| LinuxSandboxWrapper | cli.js | line ~750 | --unshare-net, --tmpfs, --ro-bind, apply-seccomp | Linux command wrapping uses bubblewrap, network namespace, bind mounts, and optional seccomp. |
| MacSandboxWrapper | cli.js | line ~751 | /usr/bin/sandbox-exec, (deny default, mach-lookup | macOS command wrapping uses sandbox-exec profile generation. |
| SandboxNetworkInfrastructure | cli.js | line ~752 | Network infrastructure initialized | Sandbox initializes HTTP/SOCKS proxy infrastructure for network filtering. |
| SandboxCommandWrapperApi | cli.js | line ~752 | wrapWithSandbox:St1 | Sandbox manager exposes the command-wrapping API. |
| SandboxRuntimeConfigConverter | cli.js | line ~791 | convertToSandboxRuntimeConfig, SandboxManager | Claude Code converts settings/permissions into a sandbox-runtime config. |
| ShellSandboxWrapCall | cli.js | line ~791 | rM.wrapWithSandbox | Shell command is transformed through the sandbox manager before execution. |
| SandboxPermissionFrames | cli.js | line ~2008, byte 0x51be67 | sandbox_permission_request, sandbox_permission_response | Sandbox-specific approvals can cross the remote/control channel. |
| ReplSandboxViolationRetry | cli.js | line ~3554 | REPL Bash sandbox violation — auto-retrying unsandboxed | REPL shell path can detect sandbox violation and retry outside sandbox when allowed. |
| ModelSandboxDefaultGuidance | cli.js | line ~5124, byte 0x95dfe5 | You should always default to running commands within the sandbox | Model-facing Bash guidance defaults commands to sandboxed execution. |
| DangerousSandboxOverrideInput | cli.js | line ~5124, byte 0x95e03e | dangerouslyDisableSandbox: true | Escape hatch exists but is permission/policy mediated. |
| SandboxWritableTempGuidance | cli.js | line ~5124, byte 0x95ddef | $TMPDIR | Runtime tells the model to use the sandbox-writable temp directory. |
| SandboxOverrideDecision | cli.js | line ~5147 | decisionReason:{type:"sandboxOverride"...} | Running outside sandbox becomes an explicit permission decision. |
| ShellSandboxDecision | cli.js | line ~5156 | shouldUseSandbox | Bash/PowerShell execution path decides whether to wrap the command. |
| SandboxConfigurationUi | cli.js | line ~7204, byte 0xb1053b | Commands will try to run in the sandbox automatically | User-visible sandbox configuration UI. |
| SandboxBlockedStatus | cli.js | line ~9355 | Sandbox blocked | TUI status line reports blocked sandbox operations. |
| StartupSandboxInitialization | cli.js | line ~19336 | if(c6.isSandboxingEnabled()){L7("before_sandbox_init")...} | Main startup initializes sandbox before running the session. |
Design overview
flowchart TD Settings[sandbox settings + managed policy] --> Manager[SandboxManager] Permissions[tool permissions / edit-read state] --> Config[Sandbox runtime config] Manager --> Config Config --> Init[initialize sandbox] Init --> Network[HTTP/SOCKS proxy + domain filter] Init --> Platform{platform} Platform -->|Linux / WSL| Linux[bubblewrap + net namespace + seccomp + socat bridge] Platform -->|macOS| Mac[sandbox-exec profile + Mach/Unix socket policy] Platform -->|unsupported| Fallback{failIfUnavailable?} Fallback -->|true| Error[startup error] Fallback -->|false| Unsandboxed[warn and run unsandboxed] Linux --> Wrap[wrapWithSandbox] Mac --> Wrap Wrap --> Shell[Bash / PowerShell command] Shell --> Result[stdout/stderr/result] Result --> Violations[violation store / hadSandboxViolation]The sandbox is not a separate always-on container. It is a command wrapper and policy service that is initialized at startup, converts current settings into a platform-specific runtime config, and wraps shell commands when the tool path says sandboxing should be used.
Configuration model
The settings schema exposes three control layers:
| Layer | Settings | Meaning |
|---|---|---|
| Availability and fallback | sandbox.enabled, sandbox.failIfUnavailable, enabledPlatforms policy | Decide whether the sandbox should run and whether missing dependencies are fatal. |
| Escape hatch policy | allowUnsandboxedCommands, autoAllowBashIfSandboxed, excludedCommands | Decide whether commands can request unsandboxed fallback and whether Bash can be auto-allowed when sandboxed. |
| Isolation policy | network, filesystem, ignoreViolations, enableWeakerNestedSandbox, enableWeakerNetworkIsolation | Define domain/socket/proxy rules, read/write path rules, ignored violation patterns, and platform-specific weakening knobs. |
Important schema details:
sandbox.failIfUnavailableis explicitly described as a hard gate for managed deployments. If false, the runtime warns and commands can run unsandboxed when sandbox initialization fails.sandbox.allowUnsandboxedCommandscontrols whether thedangerouslyDisableSandboxparameter is honored. When false, the parameter is ignored and commands must run sandboxed.sandbox.network.allowedDomains/deniedDomainsdefine network policy, with managed-only modes such asallowManagedDomainsOnly.sandbox.filesystem.allowWrite,denyWrite,denyRead, andallowReaddefine path policy. Edit/Read permission rules can feed those lists.bwrapPathandsocatPathare Linux/WSL-only and only honored from admin-controlled managed settings.
Execution path
The shell tool path decides whether a command should be sandboxed:
- Bash/PowerShell receives tool input, including optional
dangerouslyDisableSandbox. - Permission checking treats unsandboxed execution as
decisionReason.type === "sandboxOverride"and can ask the user/host with the messageRun outside of the sandbox. shouldUseSandboxreturns false if sandboxing is disabled, the command is excluded, or an allowed unsandboxed override is present.- When sandboxing is enabled,
c6.wrapWithSandboxdelegates torM.wrapWithSandbox. - The platform wrapper rewrites the command string to run through Linux
bwrap/seccomp/proxy setup or macOSsandbox-exec. - Results carry normal stdout/stderr plus sandbox-specific violation metadata when detected.
sequenceDiagram autonumber participant Model as Model/tool input participant Bash as Bash tool participant Perm as Permission resolver participant SM as SandboxManager participant OS as Platform sandbox participant Store as Violation store
Model->>Bash: command + optional dangerouslyDisableSandbox Bash->>Perm: check permissions Perm-->>Bash: allow / ask sandboxOverride / deny Bash->>SM: shouldUseSandbox + wrapWithSandbox SM->>OS: build platform command wrapper OS-->>Bash: sandboxed command string Bash->>OS: execute OS-->>Bash: result or violation Bash->>Store: record violations / annotate stderrLinux and WSL design
The Linux/WSL path uses a layered sandbox:
| Mechanism | Evidence | Purpose |
|---|---|---|
bubblewrap / bwrap | Dependency checks and bwrapPath setting | Create mount/user/network namespace wrappers. |
--unshare-net | Linux wrapper code | Remove direct network access from the command and route through controlled proxies. |
| HTTP/SOCKS proxy bridge | socatPath, claude-http-*.sock, claude-socks-*.sock strings | Bridge sandboxed traffic to local proxy ports while preserving filtering. |
| Optional seccomp | apply-seccomp, seccomp not available - unix socket access not restricted | Restrict Unix socket access when support binaries exist. |
| Bind mounts and tmpfs | --ro-bind, --bind, --tmpfs, denyRead, allowRead | Enforce read/write policy by mounting allowed/denied paths into the namespace. |
$TMPDIR | Model-facing instruction | Provide a sandbox-writable temp path and discourage direct /tmp use. |
The code explicitly handles dependency failures: missing bwrap or socat are errors for a full Linux sandbox; missing seccomp produces a warning that Unix socket access is not fully restricted.
macOS design
The macOS path generates a sandbox-exec profile:
- It creates a profile starting with
(deny default ...)and then adds essential allowances. - It has explicit policy for Mach IPC, Unix sockets, local binding, and XPC/Mach lookup services.
- It can allow a weaker network-isolation mode for
com.apple.trustd.agent, with a schema warning that this reduces security. - It can start a macOS sandbox log monitor and record violations, with
ignoreViolationssupport.
This is a different implementation from Linux: macOS uses a profile language and system sandbox command; Linux uses namespace/mount/proxy/seccomp wrapping.
Network filtering
Network restrictions are proxy-mediated:
- The sandbox runtime starts or uses HTTP/SOCKS proxy ports.
- The filter checks
deniedDomainsfirst, thenallowedDomains. - If no rule matches and a permission callback exists, it can ask the user/host.
- Denied requests return a sandbox-runtime 403 response or block the connection.
- Optional TLS termination can generate an ephemeral CA so request bodies are visible to the filter.
The remote/control schema includes sandbox_permission_request and sandbox_permission_response, so a sandbox network approval can cross the same control channel as tool permissions when the host is remote or SDK-driven.
Filesystem filtering
Filesystem policy is derived from settings and permission rules:
denyReaddenies broad read regions;allowReadcan re-allow subpaths inside those regions.allowWriteis merged with paths allowed by edit permissions;denyWritetakes precedence within allowed write regions.- Linux expands glob read patterns but skips glob write patterns on Linux/WSL, warning about unsupported write glob patterns.
- The runtime can plant/scrub protective bare-repo markers and has special handling around Git config/hooks.
The model-facing Bash prompt summarizes current sandbox filesystem/network policy and warns not to add sensitive paths such as shell RC files, SSH keys, or credential files to allowlists.
Unsandboxed fallback and strict mode
The sandbox has two user-visible operating styles:
| Mode | Behavior |
|---|---|
| Allow unsandboxed fallback | Commands default to sandbox; if a command appears to fail because of sandbox restrictions, the model may retry with dangerouslyDisableSandbox: true, which prompts for permission. |
| Strict sandbox mode | dangerouslyDisableSandbox is disabled by policy; all model-invoked Bash commands must run sandboxed or be explicitly excluded. |
The runtime guidance is intentionally conservative: default to sandboxed execution, treat each unsandboxed command individually, and explain the likely restriction when retrying outside the sandbox.
Failure modes and observable behavior
| Failure or event | Runtime behavior |
|---|---|
| Sandbox enabled but platform unsupported | If failIfUnavailable is true, startup errors; otherwise warning/fallback. |
| Missing Linux dependencies | Reports missing bubblewrap/socat; strict deployments can fail startup. |
| Seccomp unavailable | Warns that Unix socket blocking is disabled; other restrictions can still apply. |
| Sandbox violation during Bash/REPL | hadSandboxViolation can be set; REPL Bash can auto-retry unsandboxed if allowed. |
| Blocked operation in TUI | Status line displays Sandbox blocked ... and points to /sandbox. |
| Settings change | Sandbox config is updated live from settings subscriptions. |
| Network request outside allowlist | Request is denied or asks through sandbox permission callback. |
Relationship to normal permissions
The sandbox is not a replacement for tool permissions. It is an OS/process isolation layer that runs after the tool is approved. Normal permission rules decide whether a command may be attempted; sandbox policy decides what the approved command can touch at runtime.
flowchart LR ToolPermission[Tool permission: may Bash run?] --> SandboxPolicy[Sandbox policy: what can the process access?] SandboxPolicy --> OS[OS wrapper] OS --> Result[success / denied / violation]Caveats
- This page documents the readable
cli.jswrapper and configuration path. It does not reverse-engineer every native or external@anthropic-ai/sandbox-runtimeimplementation detail. - Exact behavior depends on platform, settings source precedence, installed dependencies, managed policy, and whether a host is available to answer permission prompts.
- Windows appears to have setting/policy surfaces, but the source-confirmed command wrapper disables sandbox use for PowerShell on Windows in the current bundle; the supported platform logic is Linux/WSL and macOS.
Related docs
Created and maintained by Yingting Huang.