Claude Code Sandbox ๐๏ธยถ
This page documents the OS-level sandbox configuration for Claude Code. The relevant keys live under sandbox in .claude/settings.json. The sandbox is the primary containment layer in this project: because the allowlist uses the wildcard Bash(*) (with autoAllowBashIfSandboxed as defence-in-depth), sandbox confinement, not the per-command allowlist, is what bounds the blast radius of Bash. The allow/ask/deny lists described in settings.md remain in force on top of it as the policy gate.
Activation ๐ขยถ
The sandbox is activated unconditionally via "sandbox": { "enabled": true }. This means filesystem and network restrictions below are enforced at every session, not only when the operator manually switches into sandbox permission mode. The OS-level sandbox is the source of truth for what commands may read, write, and reach over the network; the allow/ask/deny permission lists remain in force as a second line of defence for policy concerns the OS cannot express (e.g. requiring confirmation before publishing a commit).
Fail-Closed on Missing Backend ๐ยถ
The settings file additionally sets "sandbox": { "failIfUnavailable": true }. This prevents a dangerous false-security state: if the OS-level sandbox backend (e.g. bwrap on Linux, sandbox-exec on macOS) is missing or non-functional, Claude Code would otherwise silently fall back to no sandboxing while autoAllowBashIfSandboxed continues to auto-approve commands as if they were confined. With failIfUnavailable: true, Claude Code refuses to proceed in that situation, forcing the operator to install the missing backend or explicitly downgrade the policy before any command runs. Contributors on systems without a working sandbox backend MUST install the appropriate binary rather than weakening this flag locally.
No Unsandboxed Escape Hatch ๐ชยถ
"sandbox": { "allowUnsandboxedCommands": false } removes the operatorโs ability to opt a single command out of the sandbox. The dangerouslyDisableSandbox: true parameter exposed by the Bash tool is rejected when this flag is false, so there is no per-call โtrust me, run this raw on the hostโ path. Commands that legitimately cannot run inside the sandbox (e.g. operations requiring access to ~/.ssh or ~/.gnupg) MUST be invoked manually by the operator outside Claude Code rather than smuggled through an unsandboxed escape.
Bash Auto-Allow โกยถ
"sandbox": { "autoAllowBashIfSandboxed": true } treats sandbox confinement as sufficient policy for Bash. It exists as defence-in-depth alongside the explicit Bash(*) allow entry in permissions.allow: with either in place, Bash commands run automatically as long as no deny or ask rule matches. The wildcard Bash(*) is the primary gate today; the flag guarantees the agent stays functional if that entry is ever narrowed or removed. This keeps the allowlist small (see settings.md) and removes the friction of extending it for every new make target or script. The trade-off is that the sandbox MUST be correct: allowWrite, denyRead, and the network rules below are now the operative policy for what Bash can touch.
Installing the Sandbox Backend ๐ฅยถ
On Linux, the sandbox backend requires bubblewrap (provides the bwrap binary) and socat. The project ships a cross-distribution installer at scripts/install/sandbox.sh that detects the distribution via /etc/os-release and installs both packages with the native package manager. Supported distributions:
Distribution |
Package manager |
Notes |
|---|---|---|
Debian, Ubuntu (+ derivatives like Mint, Pop!_OS, Raspbian) |
|
Uses |
Fedora |
|
|
CentOS, RHEL, Rocky Linux, AlmaLinux |
|
CentOS/RHEL 7 need EPEL enabled out-of-band. |
Arch, Manjaro, EndeavourOS |
|
Installs from |
Invoke it via the dedicated Make target (preferred, matches the agent permission model in .claude/settings.json):
make install-agent
Equivalent direct invocation:
bash scripts/install/sandbox.sh
Both paths elevate privileges via sudo when not run as root, and the script verifies bwrap and socat on PATH before it exits. macOS uses sandbox-exec from the base system and does not need this target.
Write Scope โ๏ธยถ
The agent MAY write to the paths listed in sandbox.filesystem.allowWrite. All other paths are read-only by default.
Path |
Purpose |
|---|---|
|
The repository working tree. Required for any code change. |
|
The only location outside the repository where transient agent output (downloaded logs, scratch files, intermediate artefacts) MAY be written; see the Temporary Files rule in |
|
Cache directory used by the pre-commit framework. Granted because pre-commit hooks run on every commit and need to populate and read this cache; without it, every commit attempt would fail with |
|
pipโs package cache. Granted because the projectโs |
|
|
|
Project-managed Python virtualenvs (notably |
|
Default parent directory of the branch worktrees created by |
|
Ansibleโs runtime state directory (notably |
Adding entries here widens the agentโs effective write scope. New paths SHOULD be justified against the same standard as the existing three (required for normal workflow, no sensitive content, narrow as possible).
Read Restrictions ๐ซยถ
The following paths are never readable, even if a task explicitly requests access:
Path |
What it protects |
|---|---|
|
GPG keys and keyrings. The agent therefore cannot create signed commits. See the GPG signing override in settings.md for how this is reconciled with |
|
Kubernetes cluster credentials. |
|
AWS access keys and configuration. |
|
Google Cloud service account credentials. |
|
Registry credentials that |
|
HTTPS credentials written by gitโs |
|
Machine credentials read by |
|
The default SSH private keys. |
The rest of ~/.ssh stays readable, because ssh needs known_hosts and config for git fetch; authentication goes through the SSH agent. See security.md (Assumption 10).
Network ๐ยถ
The sandbox.network block governs outbound and local connectivity from inside the sandbox.
Field |
Current value |
Effect |
|---|---|---|
|
List of domain patterns the agent or its tooling needs to reach. Apex domains are listed bare ( |
Subdomain wildcards ( |
|
|
The sandbox can connect to any Unix-domain socket on the host. Required so commands like |
|
|
The agent MAY bind listening sockets on |
If a contributor needs to tighten network policy locally (e.g. running on an untrusted network), they SHOULD do so via .claude/settings.local.json rather than weakening the project-level defaults that other contributors depend on.