Skip to content

Sandbox and isolation

This page uses reverse-engineered cli.renamed.js anchors to answer the sandbox question: 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, macOS, and a feature-gated Windows path with different OS mechanisms, exposes network and filesystem restrictions, and can ask for permission or fall back outside the sandbox depending on policy.

Source anchors

Semantic aliasString or symbolMeaning
SandboxViolationMetadatahadSandboxViolationShell failures can carry sandbox-violation metadata.
SandboxStartupProfilersandbox_init, before_sandbox_init, after_sandbox_initStartup profiling treats sandbox init as an explicit phase.
SandboxWriteAllowlistallowWrite:y.arrayFilesystem write allowlist setting.
SandboxFailIfUnavailablefailIfUnavailable:y.booleanStartup can hard-fail if sandbox is required but unavailable.
UnsandboxedCommandPolicyallowUnsandboxedCommands:y.booleanPolicy knob controlling whether dangerouslyDisableSandbox can bypass isolation.
BubblewrapPathPolicybwrapPathLinux/WSL bubblewrap binary override from managed settings.
SocatPathPolicysocatPathLinux/WSL socat override for sandbox network proxy.
SandboxManagedPolicyMergesandbox.enabled, sandbox.failIfUnavailable, sandbox.network, sandbox.filesystemManaged settings merge preserves sandbox policy controls.
SandboxSettingsValidatorenabled, failIfUnavailable, allowUnsandboxedCommands, network, filesystem, ignoreViolationsSettings-key validator recognizes sandbox settings.
SandboxCredentialSettingssandbox.credentials.files, sandbox.credentials.envVars, allowPlaintextInjectProtects credential paths and secret environment variables inside sandboxed commands.
SandboxRuntimePackage@anthropic-ai/sandbox-runtimeThe bundle includes the package’s JavaScript orchestration; platform/native helpers remain separate enforcement boundaries.
LinuxSandboxDependencyChecksbubblewrap (bwrap) not installed, socat not installedLinux dependency checks.
LinuxSandboxWrapper--unshare-net, --tmpfs, --ro-bind, apply-seccompLinux command wrapping uses bubblewrap, network namespace, bind mounts, and optional seccomp.
MacSandboxWrapper/usr/bin/sandbox-exec, (deny default, mach-lookupmacOS command wrapping uses sandbox-exec profile generation.
WindowsSandboxGateCLAUDE_CODE_NANKEEN_KESTREL, tengu_nankeen_kestrel, Qnt()Windows sandbox support is present but requires an environment or feature-gate enablement ~242,468.
WindowsSandboxInstallerinstallWindowsSandbox, srt-win install, ClaudeCodeSandboxOne-time elevated setup provisions a dedicated user and WFP filters ~231,845-231,910.
WindowsSandboxWrapperwrapWithSandboxArgv, srt-win execWindows uses an argv/env wrapper and a non-shell spawn rather than the Unix shell-string wrapper ~232,050-232,090, ~232,850-232,930.
SandboxNetworkInfrastructureNetwork infrastructure initializedSandbox initializes HTTP/SOCKS proxy infrastructure for network filtering.
SandboxCommandWrapperApiSandboxManager.wrapWithSandbox, SandboxManager.wrapWithSandboxArgvThe manager exposes string wrapping for Unix-like hosts and argv wrapping for Windows.
SandboxRuntimeConfigConverterconvertToSandboxRuntimeConfig, SandboxManagerClaude Code converts settings/permissions into a sandbox-runtime config.
ShellSandboxWrapCallSandboxManager.wrapWithSandbox, SandboxManager.wrapWithSandboxArgvShell execution selects the platform-appropriate manager API ~328,680-328,720.
SandboxPermissionFramessandbox_permission_request, sandbox_permission_responseSandbox-specific approvals can cross the remote/control channel.
ReplSandboxViolationRetryREPL Bash sandbox violation — auto-retrying unsandboxedREPL shell path can detect sandbox violation and retry outside sandbox when allowed.
ModelSandboxDefaultGuidanceYou should always default to running commands within the sandboxModel-facing Bash guidance defaults commands to sandboxed execution.
DangerousSandboxOverrideInputdangerouslyDisableSandbox: trueEscape hatch exists but is permission/policy mediated.
SandboxWritableTempGuidance$TMPDIRRuntime tells the model to use the sandbox-writable temp directory.
SandboxOverrideDecisiondecisionReason:{type:"sandboxOverride"...}Running outside sandbox becomes an explicit permission decision.
ShellSandboxDecisionshouldUseSandboxBash/PowerShell execution path decides whether to wrap the command.
SandboxConfigurationUiCommands will try to run in the sandbox automaticallyUser-visible sandbox configuration UI.
SandboxBlockedStatusSandbox blockedTUI status line reports blocked sandbox operations.
StartupSandboxInitializationSandboxManager.isSandboxingEnabled(), before_sandbox_init, SandboxManager.initialize(...)Main startup checks required/unavailable behavior and initializes the sandbox before running the session ~950,800-950,900.

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 -->|Windows + gate| Windows[srt-win + dedicated user + ACL + WFP]
Platform -->|unsupported| Fallback{failIfUnavailable?}
Fallback -->|true| Error[startup error]
Fallback -->|false| Unsandboxed[warn and run unsandboxed]
Linux --> Wrap[wrapWithSandbox string]
Mac --> Wrap
Windows --> Argv[wrapWithSandboxArgv]
Wrap --> Shell[Bash / PowerShell process]
Argv --> Shell
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 four 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.
Credential isolationcredentials.files, credentials.envVars, credentials.allowPlaintextInjectDeny file reads, unset env vars, or mask/inject env credentials through the egress proxy.

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.
  • Windows additionally requires Qnt() to pass: CLAUDE_CODE_NANKEEN_KESTREL or the tengu_nankeen_kestrel feature gate must be enabled. Bundle presence alone does not activate the Windows path.

Credential isolation

sandbox.credentials is separate from the general filesystem/network lists:

EntryModesBehavior
files[]deny onlyBlocks reads of the named credential file or directory inside the sandbox. Paths resolve like other sandbox filesystem paths.
envVars[]deny / maskdeny removes the variable. mask exposes a sentinel in the sandbox and lets the host proxy replace it with the real value only on egress.
envVars[].injectHostsapplies to maskNarrows substitution to named reachable hosts; if omitted, allowed network domains are used.
allowPlaintextInjectboolean, default falseAllows sentinel replacement on plain HTTP. It is ignored from project/local settings and should be reserved for trusted test fixtures.

mask is an environment-variable mode in Claude Code’s settings schema; credential-file entries expose only deny. Sentinel replacement operates on proxy-visible HTTP headers, not arbitrary binary protocols. The runtime warns when mask entries exist without a usable proxy/TLS path, because merely placing a sentinel in the child environment does not make arbitrary plaintext egress safe.

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. On Linux/WSL and macOS, SandboxManager.wrapWithSandbox returns a rewritten shell command. On Windows, SandboxManager.wrapWithSandboxArgv returns {argv, env, unsetEnv} for a direct, non-shell spawn.
  5. The platform wrapper routes through Linux bwrap/seccomp/proxy setup, macOS sandbox-exec, or Windows srt-win exec under the provisioned sandbox user.
  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/Argv
SM->>OS: build platform command wrapper
OS-->>Bash: sandboxed command string or argv/env
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.

Windows design (feature-gated)

The current bundle contains a complete JavaScript orchestration path for Windows, but it is not unconditionally available. Qnt() returns true only on Windows and only when CLAUDE_CODE_NANKEEN_KESTREL or the tengu_nankeen_kestrel feature gate enables it. When that gate is off, startup reports that the Windows sandbox is not active rather than treating the embedded code as usable.

The enabled path uses srt-win.exe and differs from both Unix implementations:

MechanismSource-confirmed behavior
One-time installation/sandbox install reaches installWindowsSandbox(), which invokes srt-win install with a UAC-capable 60-second operation. It provisions the dedicated ClaudeCodeSandbox user and installs WFP filters.
Network fenceInitialization verifies that the dedicated user’s direct outbound probe is blocked outside the proxy port range. The default WFP permit range is 60080-60089; the in-process HTTP/SOCKS mux proxy performs domain filtering inside that fence.
Filesystem policySession initialization resolves existing paths, grants allowed read/write access, and stamps deny ACLs for the sandbox user’s SID. Reset revokes grants and restores stamped ACLs; anomalous outcomes are logged for srt-win acl recover.
Command launchWindows cannot use the shell-string wrapWithSandbox() API. wrapWithSandboxArgv() produces srt-win exec ... -- <shell> <command> plus env additions/removals, and Claude Code spawns that argv with shell: false.
Shell selectionPowerShell and Git Bash are both routed through the argv wrapper. Sandboxed Bash requires an absolute bash-family executable or an installed Git Bash fallback.
TLS credential injectionTLS termination requires persistent CA certificate/key paths and a matching CA already trusted in the sandbox user’s Root store. The runtime does not install an ephemeral per-session CA into that account.

Windows filesystem ACLs are session-wide. updateConfig() can refresh proxy/domain configuration live, but if the effective file-access set changes it warns that a reset() followed by initialize() is required; the previously applied ACL set remains active until then. Per-command Windows overrides may add deny paths, but per-command allowRead/allowWrite is rejected because srt-win exec exposes only per-exec denies.

The argv builder also enforces the Windows CreateProcessW command-line limit. Near 30,000 assembled characters it raises a dedicated error; PowerShell’s encoded-script expansion leaves roughly 10,000 source characters in the documented worst case, so the suggested recovery is to write a script file or split the command.

Network filtering

Network restrictions are proxy-mediated:

  1. The sandbox runtime starts or uses HTTP/SOCKS proxy ports. Linux bridges its network namespace through socat; Windows WFP confines the dedicated sandbox user to the proxy port range.
  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. On Linux/macOS, optional TLS termination can generate an ephemeral CA so request bodies are visible to the filter. Windows requires persistent CA paths and a matching certificate already trusted by the sandbox account.

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.
  • Windows resolves existing policy paths into session-wide grant/deny ACL operations; live filesystem-policy changes require sandbox reset/reinitialization.
  • 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; model-invoked shell commands must run sandboxed or be explicitly excluded. Windows additionally refuses compound commands when only a partial exclusion would otherwise bypass the sandbox.

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.
Windows feature gate offReports that the Windows sandbox is not active for the session; strict policy can refuse startup or command execution rather than silently bypassing it.
Windows setup incompleteMissing srt-win, dedicated-user credentials, WFP filters, or a matching trusted TLS CA makes dependency/init checks fail and points to /sandbox install or administrator remediation.
Windows command too longwrapWithSandboxArgv raises SandboxCommandTooLongError before spawn and recommends a script file or smaller commands.
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 Claude Code’s wrapper plus the readable JavaScript from bundled @anthropic-ai/sandbox-runtime. It does not reverse-engineer native helpers such as srt-win.exe, kernel/OS enforcement internals, or every host-dependent filesystem behavior.
  • Exact behavior depends on platform, settings source precedence, installed dependencies, managed policy, and whether a host is available to answer permission prompts.
  • Windows support is source-confirmed but feature-gated and installation-dependent. Presence in the bundle does not prove that a given account/session can enable it.

Subprocess env scrub and egress gateway

The SandboxScrub module (cli.renamed.js:237151-238180) layers a stricter bubblewrap/env-scrub regime on top of the regular sandbox. It is gated by CLAUDE_CODE_SUBPROCESS_ENV_SCRUB and is the source of the hosted-runtime hardening referenced in Built-in tools and permissions; it is separate from the Windows srt-win path.

Scrub gates

PredicateBehavior
isScrubEnabled()True iff CLAUDE_CODE_SUBPROCESS_ENV_SCRUB is set. Latched once per process.
at1()Returns true when isScrubEnabled() OR (env unset AND CLAUDE_CODE_ENTRYPOINT === "local-agent"). The local-agent path opts in by default.
isScrubSandboxAvailable()True when bubblewrap (bwrap) is found. Latched once per process.
assertScrubSandboxAvailable()Hard assertion at startup. If bwrap is missing, throws either sandbox.bwrapPath is set but not executable or bubblewrap is required for subprocess env scrubbing with install/disable instructions.
shouldUseMcpAllowlistEnv()True for CLAUDE_CODE_MCP_ALLOWLIST_ENV=1 or CLAUDE_CODE_ENTRYPOINT === "local-agent".

Startup priming (assertScrubSandboxAvailable)

The scrub bootstrap pre-creates files and directories the bubblewrap mount layout requires (without these stubs the sandbox bind mount fails for missing paths). Pre-created files include shell config (.gitconfig, .bash_profile, .bashrc, .bash_aliases, .profile, .zshrc), package manager config (.bunfig.toml, .npmrc, .yarnrc, .yarnrc.yml, bunfig.toml, package.json, package-lock.json, yarn.lock, pnpm-lock.yaml), repo config (.gitmodules), auth files (.netrc), the inline-comments buffer (/tmp/inline-comments-buffer.jsonl), and every entry in the env-file list (.env, .env.local, …, .env.production.local).

Pre-created directories include: ~/.config/{gh,git,pip}, ~/.pip, <cwd>/.claude/{commands,agents}, <cwd>/node_modules/.bin, the GitHub Actions RUNNER_FILE_COMMANDS_DIR, and every entry in PATH that falls under a writable mount root.

For GitHub Actions, when the workspace differs from the cwd, the runtime also pre-creates <workspace>/.git/{hooks,modules,info}, <workspace>/.github, and stub .git/config/.gitmodules/.git/info/exclude files. It then appends a # claude-code scrub-mode stubs block to <cwd>/.git/info/exclude so the stub files are ignored by Git.

Script-call caps (enforceScriptCaps)

CLAUDE_CODE_SCRIPT_CAPS is an env var holding JSON like {"curl": 3, "wget": 1}. Parsed once into the in-process cap map. enforceScriptCaps(command):

  1. Returns early when scrub is disabled.
  2. For each cap entry, counts substring matches of the command string (command.split(key).length - 1).
  3. Accumulates the per-key count across the whole process lifetime.
  4. Throws Script call limit exceeded: <key> has been called <n> times (cap: <c>). This limit prevents data exfiltration via repeated write operations in untrusted-input workflows. when the cap is exceeded.

This is a per-process accumulating cap, not per-tool-call; it survives across multiple shell invocations in the same session.

Egress gateway (registerEgressGatewayEnvFn, egressGatewayEnv)

registerEgressGatewayEnvFn(fn) lets the network proxy layer install a callback that returns extra env vars (proxy hostname, auth headers, etc.). egressGatewayEnv() reads the callback’s output or returns {}. The result feeds subprocessEnv().

subprocessEnv()

The canonical env-for-subprocess builder. It composes base process.env + color env + egressGatewayEnv() + (when CLAUDE_CODE_REMOTE is set) remote-aware env from cQK(...), then strips a fixed list of secret-bearing env vars before handing the env to the child:

  • CLAUDE_CODE_OAUTH_TOKEN, CLAUDE_CODE_SUBSCRIPTION_TYPE, CLAUDE_CODE_RATE_LIMIT_TIER, CLAUDE_BG_AUTH_SNAPSHOT_PATH.
  • CLAUDE_CODE_SESSION_KIND, CLAUDE_BG_SOURCE, CLAUDE_BG_ISOLATION, CLAUDE_BG_BACKEND, CLAUDE_CODE_SESSION_NAME, CLAUDE_CODE_RESUME_INTERRUPTED_TURN.
  • Every OTEL_* env var.

When scrub is active (at1() true), it additionally drops every entry in the protected secret list (ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN, ANTHROPIC_FOUNDRY_API_KEY, ANTHROPIC_AWS_API_KEY, ANTHROPIC_BEDROCK_MANTLE_API_KEY, ANTHROPIC_CUSTOM_HEADERS, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN, AWS_BEARER_TOKEN_BEDROCK, GOOGLE_APPLICATION_CREDENTIALS, AZURE_CLIENT_SECRET, AZURE_CLIENT_CERTIFICATE_PATH, ACTIONS_ID_TOKEN_REQUEST_TOKEN, ACTIONS_ID_TOKEN_REQUEST_URL, ACTIONS_RUNTIME_TOKEN, ACTIONS_RUNTIME_URL, ALL_INPUTS, OVERRIDE_GITHUB_TOKEN, DEFAULT_WORKFLOW_TOKEN, SSH_SIGNING_KEY) AND their INPUT_<NAME> GitHub-Actions counterparts.

This is what makes a scrub-mode subprocess unable to read ANTHROPIC_API_KEY or AWS_SECRET_ACCESS_KEY even when the parent process has them set.

Sandbox filesystem path resolution

The SandboxFilesystem module (cli.renamed.js:237955-238180) decides which paths the bubblewrap sandbox bind-mounts and how the model’s settings translate to the sandbox runtime config.

resolvePathPatternForSandbox(pattern, source)

Resolves a per-settings-source path pattern: //absolute/path strips the leading / and treats it as absolute; /relative/to/settings/root resolves against getSettingsRootPathForSource(source); otherwise passes through unchanged. resolveSandboxFilesystemPath(path, source) is the same logic for sandbox-config filesystem entries (no Read/Write rule conversion).

Managed-only modes

shouldAllowManagedSandboxDomainsOnly() is true when any policy tier sets sandbox.network.allowManagedDomainsOnly: true. In this mode convertToSandboxRuntimeConfig(...) builds the allowed-domain list only from managed-policy settings and ignores user/project allow lists. The same rule applies to allowRead paths via sandbox.filesystem.allowManagedReadPathsOnly.

convertToSandboxRuntimeConfig(settings)

The central translator. Produces the common network, filesystem, credentials, violation, ripgrep, and platform-weakening fields; Linux receives seccomp/bwrapPath/socatPath, macOS receives Apple-event policy, and Windows receives the sandbox-user plus srtWin descriptor. Highlights:

  • Walks every settings source via FJ, resolving path patterns relative to that source’s root. WebFetch(domain:...) allow/deny rules feed network domains, while Read/Edit path rules feed filesystem allowRead/denyRead/allowWrite/denyWrite entries.
  • The allowWrite list is seeded with . (cwd) and the sandbox staging directory.
  • Includes the settings file for every source, plus WSL managed-settings paths when running under WSL.
  • When cwd differs from original cwd, also includes the cwd’s .claude/settings.json and .claude/settings.local.json and the cwd’s .claude/skills directory.
  • For each cwd that exists (current + original), bind-mounts <cwd>/HEAD, <cwd>/objects, <cwd>/refs if Git artifacts are present; on macOS, also pre-records missing artifacts so they can later be scrubbed.
  • Adds every additionalDirectories entry from settings AND from getAdditionalDirectoriesForClaudeMd() (additional cwds discovered via --add-dir and similar).
  • Network policy: when scrub is enabled AND sandbox is available AND !isSandboxEnabledInSettings(), hard-codes {allowedDomains: undefined, deniedDomains: [], allowAllUnixSockets: true} — the scrub-mode default is “trust nothing on the network” because the egress gateway already enforces it.
  • Picks the ripgrep binary descriptor so the sandbox process can run rg inside.
  • Includes seccomp and bwrap paths.
  • On Windows, adds {windows: {sandboxUser: "ClaudeCodeSandbox", srtWin: {path: process.execPath}}}; the embedded executable is invoked with the --srt-win prefix.

isSandboxEnabledInSettings / isAutoAllowBashIfSandboxedEnabled / areUnsandboxedCommandsAllowed / isSandboxRequired

  • isSandboxEnabledInSettings() — true when tengu_sandbox_gb_config.disableNoSandbox is set AND scrub is OFF, OR when settings.sandbox.enabled === true.
  • isAutoAllowBashIfSandboxedEnabled() — disabled when scrub is on or on Windows; otherwise settings.sandbox.autoAllowBashIfSandboxed, default true.
  • areUnsandboxedCommandsAllowed()settings.sandbox.allowUnsandboxedCommands, default true.
  • isSandboxRequired()isSandboxEnabledInSettings() && isPlatformInEnabledList() && settings.sandbox.failIfUnavailable. When true, missing sandbox kills the session at boot rather than running unsandboxed.

Created and maintained by Yingting Huang.