Skip to content

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 aliasSourceApproximate locationString or symbolMeaning
SandboxViolationMetadatacli.jsline ~53hadSandboxViolationShell failures can carry sandbox-violation metadata.
SandboxStartupProfilercli.jsline ~64sandbox_init, before_sandbox_init, after_sandbox_initStartup profiling treats sandbox init as an explicit phase.
SandboxWriteAllowlistcli.jsline ~185, byte 0x10a185allowWrite:y.arrayFilesystem write allowlist setting.
SandboxFailIfUnavailablecli.jsline ~185, byte 0x10a4dffailIfUnavailable:y.booleanStartup can hard-fail if sandbox is required but unavailable.
UnsandboxedCommandPolicycli.jsline ~185, byte 0x10a663allowUnsandboxedCommands:y.booleanPolicy knob controlling whether dangerouslyDisableSandbox can bypass isolation.
BubblewrapPathPolicycli.jsline ~185, byte 0x10aa5dbwrapPathLinux/WSL bubblewrap binary override from managed settings.
SocatPathPolicycli.jsline ~185, byte 0x10ab72socatPathLinux/WSL socat override for sandbox network proxy.
SandboxManagedPolicyMergecli.jsline ~187sandbox.enabled, sandbox.failIfUnavailable, sandbox.network, sandbox.filesystemManaged settings merge preserves sandbox policy controls.
SandboxSettingsValidatorcli.jsline ~188enabled, failIfUnavailable, allowUnsandboxedCommands, network, filesystem, ignoreViolationsSettings-key validator recognizes sandbox settings.
SandboxRuntimePackageLookupcli.jsline ~748@anthropic-ai/sandbox-runtimeRuntime searches for the external sandbox-runtime package.
LinuxSandboxDependencyCheckscli.jsline ~748bubblewrap (bwrap) not installed, socat not installedLinux dependency checks.
LinuxSandboxWrappercli.jsline ~750--unshare-net, --tmpfs, --ro-bind, apply-seccompLinux command wrapping uses bubblewrap, network namespace, bind mounts, and optional seccomp.
MacSandboxWrappercli.jsline ~751/usr/bin/sandbox-exec, (deny default, mach-lookupmacOS command wrapping uses sandbox-exec profile generation.
SandboxNetworkInfrastructurecli.jsline ~752Network infrastructure initializedSandbox initializes HTTP/SOCKS proxy infrastructure for network filtering.
SandboxCommandWrapperApicli.jsline ~752wrapWithSandbox:St1Sandbox manager exposes the command-wrapping API.
SandboxRuntimeConfigConvertercli.jsline ~791convertToSandboxRuntimeConfig, SandboxManagerClaude Code converts settings/permissions into a sandbox-runtime config.
ShellSandboxWrapCallcli.jsline ~791rM.wrapWithSandboxShell command is transformed through the sandbox manager before execution.
SandboxPermissionFramescli.jsline ~2008, byte 0x51be67sandbox_permission_request, sandbox_permission_responseSandbox-specific approvals can cross the remote/control channel.
ReplSandboxViolationRetrycli.jsline ~3554REPL Bash sandbox violation — auto-retrying unsandboxedREPL shell path can detect sandbox violation and retry outside sandbox when allowed.
ModelSandboxDefaultGuidancecli.jsline ~5124, byte 0x95dfe5You should always default to running commands within the sandboxModel-facing Bash guidance defaults commands to sandboxed execution.
DangerousSandboxOverrideInputcli.jsline ~5124, byte 0x95e03edangerouslyDisableSandbox: trueEscape hatch exists but is permission/policy mediated.
SandboxWritableTempGuidancecli.jsline ~5124, byte 0x95ddef$TMPDIRRuntime tells the model to use the sandbox-writable temp directory.
SandboxOverrideDecisioncli.jsline ~5147decisionReason:{type:"sandboxOverride"...}Running outside sandbox becomes an explicit permission decision.
ShellSandboxDecisioncli.jsline ~5156shouldUseSandboxBash/PowerShell execution path decides whether to wrap the command.
SandboxConfigurationUicli.jsline ~7204, byte 0xb1053bCommands will try to run in the sandbox automaticallyUser-visible sandbox configuration UI.
SandboxBlockedStatuscli.jsline ~9355Sandbox blockedTUI status line reports blocked sandbox operations.
StartupSandboxInitializationcli.jsline ~19336if(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:

LayerSettingsMeaning
Availability and fallbacksandbox.enabled, sandbox.failIfUnavailable, enabledPlatforms policyDecide whether the sandbox should run and whether missing dependencies are fatal.
Escape hatch policyallowUnsandboxedCommands, autoAllowBashIfSandboxed, excludedCommandsDecide whether commands can request unsandboxed fallback and whether Bash can be auto-allowed when sandboxed.
Isolation policynetwork, filesystem, ignoreViolations, enableWeakerNestedSandbox, enableWeakerNetworkIsolationDefine domain/socket/proxy rules, read/write path rules, ignored violation patterns, and platform-specific weakening knobs.

Important schema details:

  • sandbox.failIfUnavailable is explicitly described as a hard gate for managed deployments. If false, the runtime warns and commands can run unsandboxed when sandbox initialization fails.
  • sandbox.allowUnsandboxedCommands controls whether the dangerouslyDisableSandbox parameter is honored. When false, the parameter is ignored and commands must run sandboxed.
  • sandbox.network.allowedDomains / deniedDomains define network policy, with managed-only modes such as allowManagedDomainsOnly.
  • sandbox.filesystem.allowWrite, denyWrite, denyRead, and allowRead define path policy. Edit/Read permission rules can feed those lists.
  • bwrapPath and socatPath are Linux/WSL-only and only honored from admin-controlled managed settings.

Execution path

The shell tool path decides whether a command should be sandboxed:

  1. Bash/PowerShell receives tool input, including optional dangerouslyDisableSandbox.
  2. Permission checking treats unsandboxed execution as decisionReason.type === "sandboxOverride" and can ask the user/host with the message Run outside of the sandbox.
  3. shouldUseSandbox returns false if sandboxing is disabled, the command is excluded, or an allowed unsandboxed override is present.
  4. When sandboxing is enabled, c6.wrapWithSandbox delegates to rM.wrapWithSandbox.
  5. The platform wrapper rewrites the command string to run through Linux bwrap/seccomp/proxy setup or macOS sandbox-exec.
  6. 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 stderr

Linux and WSL design

The Linux/WSL path uses a layered sandbox:

MechanismEvidencePurpose
bubblewrap / bwrapDependency checks and bwrapPath settingCreate mount/user/network namespace wrappers.
--unshare-netLinux wrapper codeRemove direct network access from the command and route through controlled proxies.
HTTP/SOCKS proxy bridgesocatPath, claude-http-*.sock, claude-socks-*.sock stringsBridge sandboxed traffic to local proxy ports while preserving filtering.
Optional seccompapply-seccomp, seccomp not available - unix socket access not restrictedRestrict Unix socket access when support binaries exist.
Bind mounts and tmpfs--ro-bind, --bind, --tmpfs, denyRead, allowReadEnforce read/write policy by mounting allowed/denied paths into the namespace.
$TMPDIRModel-facing instructionProvide 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 ignoreViolations support.

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:

  1. The sandbox runtime starts or uses HTTP/SOCKS proxy ports.
  2. The filter checks deniedDomains first, then allowedDomains.
  3. If no rule matches and a permission callback exists, it can ask the user/host.
  4. Denied requests return a sandbox-runtime 403 response or block the connection.
  5. 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:

  • denyRead denies broad read regions; allowRead can re-allow subpaths inside those regions.
  • allowWrite is merged with paths allowed by edit permissions; denyWrite takes 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:

ModeBehavior
Allow unsandboxed fallbackCommands 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 modedangerouslyDisableSandbox 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 eventRuntime behavior
Sandbox enabled but platform unsupportedIf failIfUnavailable is true, startup errors; otherwise warning/fallback.
Missing Linux dependenciesReports missing bubblewrap/socat; strict deployments can fail startup.
Seccomp unavailableWarns that Unix socket blocking is disabled; other restrictions can still apply.
Sandbox violation during Bash/REPLhadSandboxViolation can be set; REPL Bash can auto-retry unsandboxed if allowed.
Blocked operation in TUIStatus line displays Sandbox blocked ... and points to /sandbox.
Settings changeSandbox config is updated live from settings subscriptions.
Network request outside allowlistRequest 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.js wrapper and configuration path. It does not reverse-engineer every native or external @anthropic-ai/sandbox-runtime implementation 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.

Created and maintained by Yingting Huang.