Configure the sandboxed Bash tool
概要
Bash コマンドとその子プロセスに対して、OS レベルでファイルシステムとネットワークの境界を強制する仕組み。コマンドごとの承認の代わりに、触れてよいファイルとネットワークドメインを定義する。
仕様
対応プラットフォーム
- macOS、Linux、WSL2 で動作する。ネイティブ Windows は非対応(WSL2 内で動かす)
- macOS は組み込みの Seatbelt を使うためインストール不要
- Linux は bubblewrap、WSL2 も bubblewrap を使う。WSL1 は bubblewrap が必要とするカーネル機能が無いため非対応
Linux / WSL2 のセットアップ
- 必要なパッケージ
bubblewrap: ファイルシステム分離を強制する非特権サンドボックスツールsocat: サンドボックスプロキシへネットワークトラフィックを中継するリレー
- インストール例:
sudo apt-get install bubblewrap socat(Ubuntu/Debian)、sudo dnf install bubblewrap socat(Fedora) /sandboxの Dependencies タブが、ripgrep/bubblewrap/socat/ seccomp filter のうち不足しているものを表示する- ripgrep は native Claude Code バイナリに同梱されている
- seccomp filter は任意で、Unix domain socket のブロックを追加する。不足時は
npm install -g @anthropic-ai/sandbox-runtimeでインストールする - 必須依存が欠けている場合、インストールするまで Dependencies タブのみが表示される。任意の seccomp filter だけが欠けている場合は他のタブと並んで表示される
- 依存チェックは起動時に走るため、パッケージ導入後は Claude Code を再起動する
- Ubuntu 24.04 以降では既定の AppArmor ポリシーが bubblewrap の user namespace 作成を妨げる。
sysctl kernel.apparmor_restrict_unprivileged_usernsが1を返す場合は/etc/apparmor.d/bwrapにbwrap用プロファイルを追加してsudo systemctl reload apparmorする。0またはキーが存在しない場合は不要 - WSL2 では、
cmd.exe/powershell.exe//mnt/c/配下の Windows バイナリの起動は Unix socket 経由で Windows ホストに渡されるため、Unix-socket 設定に従う(そもそもブロックするには任意の seccomp filter が必要)。許可するにはallowAllUnixSockets、サンドボックス外に出すにはexcludedCommands
/sandbox パネル
- Mode: サンドボックス化されたコマンドの承認方法を選ぶ
- Overrides: サンドボックスで失敗したコマンドが非サンドボックスで再実行できるかを選ぶ(
allowUnsandboxedCommands設定) - Config: 解決済みのサンドボックス設定を表示する
- Linux で任意の seccomp filter が欠けているときは Dependencies タブが加わる
- パネルでモードを選ぶと、プロジェクトの
.claude/settings.local.jsonに保存される。その際 Claude Code はこのファイルをグローバル gitignore に追加する - 全プロジェクトで有効にするには
~/.claude/settings.jsonのsandbox.enabledをtrueにする
サンドボックスのモード
Auto-allow mode: サンドボックス化できるコマンドをサンドボックス内で実行し、確認なしに自動承認する。サンドボックス化できないコマンド(許可されていないホストへのネットワークアクセスが必要なものなど)は通常の permission フローにフォールバックする。
auto-allow モードでも次は適用される:
- 明示的な deny ルールは常に尊重される
/、ホームディレクトリ、その他の重要システムパスを対象とするrm/rmdirは permission prompt(auto mode では classifier チェック。classifier routing は v2.1.218 以降)を発生させるBash(git push *)のような content-scoped な ask ルールはサンドボックス化されたコマンドでもプロンプトを強制する- 素の
Bashask ルール(Bash(*)も同じ)はサンドボックスで動くコマンドについてはスキップされる。通常の permission フローにフォールバックしたコマンドには適用される。plan mode ではスキップされず、read-only を含むサンドボックス化コマンドにもプロンプトが出る。v2.1.212 より前は plan mode でもスキップされていた
Regular permissions mode: サンドボックス化されていても、すべての Bash コマンドが通常の permission フローを通る。
- どちらのモードでもファイルシステムとネットワークの制限は同じ。違いは自動承認するかどうかだけ
- auto-allow モードは permission mode の設定とは独立に働く。例外は plan mode で、そこでは auto-allow が承認範囲を広げない
一時ディレクトリ
- 既定でセッションの一時ディレクトリは作業ディレクトリと並んでサンドボックス内で書き込み可能
- filesystem isolation を無効にしていない限り、サンドボックス化コマンドの
$TMPDIRはこのディレクトリに設定される - 非サンドボックスのコマンドはシェルの
$TMPDIRをそのまま継承するため、両者で$TMPDIRの解決先が異なる。両者間で一時ファイルを渡すには作業ディレクトリ配下に書く
escape hatch(dangerouslyDisableSandbox)
- サンドボックス制限でコマンドが失敗すると、Claude は失敗を解析して
dangerouslyDisableSandboxパラメータ付きで再実行することがある - 再実行されたコマンドはサンドボックス外で動くため通常の permission フローを通る。default モードでは確認プロンプト、auto mode では classifier が元のコマンドを評価する
- auto mode でも毎回プロンプトを出させるには
Bash(dangerouslyDisableSandbox:true)の ask ルールを追加する "allowUnsandboxedCommands": falseにすると escape hatch を無効化できる(/sandboxの Overrides タブでは Strict sandbox mode と表示される)。このときパラメータは完全に無視され、すべてのコマンドはサンドボックス内で動くかexcludedCommandsに明示的に列挙されている必要がある
filesystem isolation
- 既定の書き込み: 現在の作業ディレクトリとそのサブディレクトリ、および
$TMPDIRが指すセッション一時ディレクトリへの読み書き - 既定の読み取り: 一部の拒否ディレクトリを除きコンピュータ全体を読める。この既定では
~/.aws/credentialsや~/.ssh/などの認証情報ファイルも読める - ブロックされるもの: 明示的な許可なしに作業ディレクトリとセッション一時ディレクトリの外のファイルを変更できない(
~/.bashrcなどのシェル設定ファイル、/bin/のシステムバイナリを含む) - Git worktrees: 作業ディレクトリが linked git worktree の場合、
git commitが ref と index を更新できるよう、メインリポジトリの共有.gitへの書き込みも許可される。その中のhooks/とconfigへの書き込みは拒否されたまま - 作業ディレクトリ外への書き込みが必要な場合は
sandbox.filesystem.allowWriteにパスを追加する。これは OS レベルで強制されるため、子プロセスを含むサンドボックス内の全コマンドが従う - 同じ filesystem 配列が複数の settings スコープで定義されている場合、配列はマージされる(置き換えではない)
sandbox.filesystem.denyWrite/denyReadで拒否し、allowReadで拒否領域内の特定パスを再許可できる。read ルールが重なる場合はより具体的なパスが勝つ"denyRead": ["~/"]+"allowRead": ["~/projects"]→~/projectsは読め、ホームの残りはブロック"allowRead": ["~/"]+"denyRead": ["~/.env"]→~/.envはブロックのまま、ホームの残りは読める
パスの接頭辞:
| 接頭辞 | 意味 | 例 |
|---|---|---|
/ | ファイルシステムルートからの絶対パス | /tmp/build はそのまま |
~/ | ホームディレクトリからの相対 | ~/.kube は $HOME/.kube |
./ または接頭辞なし | project settings ではプロジェクトルート、user settings では ~/.claude からの相対 | project settings の ./output は <project-root>/output |
- この構文は Read / Edit の permission ルール(絶対が
//path、プロジェクト相対が/path)とは異なる
filesystem isolation の無効化
sandbox.filesystem.disabledをtrueにすると、network isolation を保ったまま filesystem isolation をスキップする- 既定は off。macOS / Linux / WSL2 に適用される。v2.1.216 以降が必要
- サンドボックスは 2 つの独立した層(filesystem isolation と network isolation)を持つ
このキーを設定できる設定ソース:
- user settings、managed settings、
--settingsCLI フラグのみ。.claude/settings.jsonと.claude/settings.local.jsonからは設定できない - managed settings が
sandbox.filesystemを設定している場合、またはsandbox.credentials.filesに"mode": "deny"のエントリがある場合、managed settings のみがこのキーを設定できる CLAUDE_CODE_SUBPROCESS_ENV_SCRUBが設定されている場合、managed settings を含むすべてのソースのfilesystem.disabledを無視し、filesystem isolation を維持する
managed の credentials.files エントリが filesystem.disabled を pin するか:
| managed エントリ | filesystem.disabled を pin するか |
|---|---|
"mode": "deny" | する |
"mode": "mask"(mask として適用) | しない |
"mode": "mask"(セットアップ時に deny へフォールバック) | しない |
"mode": "mask"(検証で deny へ降格) | する(明示的な deny と同様) |
filesystem isolation を off にしたときの影響:
| 保護 | filesystem isolation off のとき |
|---|---|
filesystem.denyRead と credentials.files の deny read ブロック | 強制されない |
credentials.envVars の deny と mask | 強制される(環境変数のスクラブは filesystem 層から独立) |
credentials.files の mask(mask として適用されたもの) | 強制される |
- サンドボックス化コマンドはセッション一時ディレクトリではなくシェルの
$TMPDIRを継承する。Linux では親シェルで未設定のことが多いため、Claude には Bash ツールのガイダンスでmktemp -dを使うよう伝えられる autoAllowBashIfSandboxedは引き続き既定trueなので、サンドボックス化コマンドはプロンプトなしで動く
network isolation
- サンドボックス外で動くプロキシサーバーでネットワークアクセスを制御する
- 既定では事前許可されたドメインは無い。 新しいドメインが必要になると承認を求める。Yes を選ぶとそのホストは現在のセッションの残りで許可され、以降は再プロンプトされない
allowedDomainsで事前許可するとプロンプトを回避できる。WebFetchの allow ルールもドメインを事前許可するstrictAllowlistをtrue(user / managed / CLI--settingsのみ)にすると、allowlist 外のホストへのアクセスをプロンプトせず拒否する。リポジトリの.claude/settings.json/.claude/settings.local.jsonで設定しても効果は無い。v2.1.219 以降- managed settings で
allowManagedDomainsOnlyを設定すると、許可外ドメインはプロンプトなしで自動ブロックされ、managed settings のallowedDomainsとWebFetch(domain:...)allow ルールのみが尊重される - 制限はコマンドが生成するすべてのスクリプト・プログラム・サブプロセスに適用される
- 組み込みプロキシは、クライアントが指定したホスト名に基づいて allowlist を強制し、既定では TLS を終端・検査しない。実験的な
network.tlsTerminate設定(v2.1.199 以降)でプロキシ自身が TLS を終端する。maskの credential エントリはこれを必要とする
sandbox.credentials
- サンドボックス化コマンドから保護する認証情報ファイルと環境変数を宣言する。v2.1.187 以降が必要
"mode": "deny"の場合、ファイルパスはサンドボックス内で読み取り拒否され(filesystem.denyReadと同じ制限)、環境変数は各サンドボックスコマンド実行前に unset される- ファイル保護は filesystem 層の一部なので filesystem isolation を無効にすると効かない。環境変数の保護は効く
- ファイルパスは
sandbox.filesystem.*と同じ接頭辞ルールに従い、denyエントリはすべての settings スコープからマージされる - 組み込みの credential deny list は無い。列挙したものだけが制限される
- サンドボックス化された Bash コマンドにのみ影響する。サンドボックスの有無に関わらず全サブプロセスから Anthropic とクラウドプロバイダの認証情報を除去するには
CLAUDE_CODE_SUBPROCESS_ENV_SCRUBを設定する
環境変数の mask
"mode": "mask"は認証情報を保護しつつ、それで認証するツールを動かし続ける。v2.1.199 以降が必要- サンドボックス化コマンドはセッションごとの sentinel 値を見る。
injectHostsに列挙したホストへリクエストが出るとき、プロキシが sentinel を実際の値に置き換える - プロキシがリクエスト内容を見る必要があるため
network.tlsTerminateの設定が要る。設定しないと mask は失敗するが情報は漏れない(sentinel がそのままサーバーに届き認証に失敗する)。この誤設定は起動時に報告される - 置換はヘッダーとリクエストボディを対象とする
injectHostsの各エントリはnetwork.allowedDomainsでカバーされている必要がある。injectHostsが無い場合はnetwork.allowedDomainsの全ホストで置換されるmaskエントリ、network.tlsTerminate、credentials.allowPlaintextInjectは user settings / managed settings /--settingsからのみ尊重される。リポジトリの.claude/settings.json/.claude/settings.local.jsonでは無視される- 同じ変数がどこかのスコープで
denyに列挙されている場合はdenyが優先される
構造を持つ値のための任意フィールド(v2.1.224 以降):
extract: 値全体に適用する正規表現。各マッチのグループ 1 が捕捉したテキストのみを置換する。少なくとも 1 つの捕捉グループが必要onExtractNoMatch: パターンが何にも一致しないときの挙動。warn(既定、警告してマスクせず通す)、deny(サンドボックス内で変数を unset)、error(設定を直すまでサンドボックスのセットアップを止める)decode: "jwt": 値が JWT であることを検証し、構造的に妥当な偽トークンに置き換える。maskClaimsで個別にマスクするトップレベル payload claim を列挙できる。JWT として検証できない場合や列挙した claim が無い場合は警告付きでマスクせず通す。extractとは併用できない
AWS リクエストの再署名
- AWS リクエストは内容に対する SigV4 署名を持つため、
AWS_ACCESS_KEY_IDとAWS_SECRET_ACCESS_KEYを一緒に mask する - プロキシは access key の sentinel から SigV4 リクエストを検出し、実際の値に置換して再署名する
- secret だけを mask するとプレースホルダで署名されたままになり検出できず AWS で失敗する。この場合は起動時に警告が出る(access key ID だけを mask した場合は出ない)
- 検出したが再署名できないリクエスト(
x-amz-dateヘッダーが無いなど)は、壊れた署名のままサーバーに届く代わりにプロキシエラーで失敗する - 慣例的な
AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY/AWS_SESSION_TOKENは値全体を mask すると自動的に 1 つの認証情報として関連付けられる。別名の場合はcredentials.awsPairsで自分でグループ化する(v2.1.224 以降)accessKeyIdVarとsecretAccessKeyVarは access key ID と secret key を保持する mask 済みenvVarsエントリを指す。任意のsessionTokenVarは一時認証情報のセッショントークンを指し、設定すると再署名リクエストにx-amz-security-tokenとして実際のトークンを送る- 各変数は
extractもdecodeも無い、値全体を mask するmaskエントリでなければならない - 再署名は access key ID エントリの
injectHostsに列挙したホストで行われる - 慣例的な変数のいずれかをペアに書くと自動ペアリングを置き換える
プロキシが再署名できない 3 形式(credentials.sigv4 で形式ごとに passthrough にできる。v2.1.224 以降):
| リクエスト形式 | sigv4 キー | 理由 |
|---|---|---|
| aws-chunked streaming uploads | streaming | チャンクごとの署名が seed 署名から連鎖するため、再署名にはボディの書き換えが必要 |
| Presigned URLs | presigned | 署名が URL 自体にあり Authorization ヘッダーが無い |
| SigV4A asymmetric signatures | sigv4a | 再計算できる共有鍵 HMAC が無い |
認証情報ファイルの mask
"mode": "mask" は v2.1.221 以降が必要。プラットフォームで挙動が異なる。
-
Linux と WSL2: サンドボックス化コマンドは secret をプレースホルダに置き換えた sentinel コピーを読み、プロキシが egress で実際の値に置換する
-
macOS: サンドボックス化コマンドは対象ファイルをまったく読めない。sentinel コピーも作られず置換もされないため
denyと同じ効果。ただしdenyと違い、filesystem isolation を無効にしても read ブロックが残る -
extractパターンでファイル内のどこが secret かを指定する。パターンは正規表現で、グループ 1 が捕捉したテキストのみを置換する。extractが無い場合はファイル内容全体を 1 つの sentinel 値に置き換える -
JWT を保持するファイルには
decode: "jwt"を設定する(v2.1.224 以降) -
onExtractNoMatch:warn(既定、警告してエントリをスキップし、サンドボックス化コマンドは実ファイルを読める)、deny(ファイルを読めなくする)、error(設定を直すまでセットアップを止める)。read ブロックが強制されない状況(filesystem isolation 無効時、filesystem.allowReadがそのパスを再開放している場合)ではdenyはerrorとして扱われる -
maskDuplicates: マッチ範囲外にある、マスク対象値の逐語コピーも置換する。生の部分文字列でマッチするため、短い・ありふれた値だとあらゆる箇所が置換される。長く高エントロピーな secret に限る。既定 false -
maskは単一ファイルに適用される。安全に mask できないエントリ(ディレクトリパス、glob パターン、8 MiB を超えるファイル、UTF-8 テキストでないファイル)はdenyにフォールバックする
組織向けの設定
{
"sandbox": {
"enabled": true,
"failIfUnavailable": true,
"allowUnsandboxedCommands": false
}
}
failIfUnavailable: Linux の bubblewrap など依存が欠けている場合に、警告して非サンドボックス実行にフォールバックするのではなく起動をブロックするallowUnsandboxedCommands: false:dangerouslyDisableSandboxの escape hatch を無視する- 既定ではサンドボックスを開始できない(依存が無い、プラットフォーム非対応)場合、警告を出して非サンドボックスで実行する。ハード失敗にするには
sandbox.failIfUnavailableをtrueにする
ポリシーを広げさせない設定:
enabledやfailIfUnavailableのような boolean キーは managed の値が使われ、ローカル設定は無視されるexcludedCommandsやallowReadのような配列キーはすべてのスコープからマージされるため、開発者が追記してポリシーを広げられるallowManagedReadPathsOnlyを managed settings でtrueにすると、managed settings のallowReadのみが尊重される。ネットワークドメインを同様に固定するにはallowManagedDomainsOnlyexcludedCommandsには managed 専用のロックダウンが無いため、開発者は常にエントリを追記できる。managed の一覧は狭く保つ
カスタムプロキシ:
{
"sandbox": {
"network": {
"httpProxyPort": 8080,
"socksProxyPort": 8081
}
}
}
他のレイヤーとの関係
| 設定・ルール | 役割 |
|---|---|
sandbox.filesystem.allowWrite | 作業ディレクトリ外のパスへのサブプロセス書き込みを許可する |
sandbox.filesystem.denyWrite / denyRead | 特定パスへのサブプロセスアクセスをブロックする |
sandbox.filesystem.allowRead | denyRead 領域内の特定パスの読み取りを再許可する |
sandbox.filesystem.disabled | network isolation を保ったまま filesystem 層を完全に切る(v2.1.216 以降) |
Edit allow ルール | sandbox.filesystem.allowWrite と同様に特定パスへの書き込みを許可する |
Read / Edit deny ルール | 特定のファイル・ディレクトリへのアクセスをブロックする |
WebFetch allow / deny ルール | ドメインアクセスを制御する |
Sandbox allowedDomains | Bash コマンドが到達できるドメインを制御する |
Sandbox deniedDomains | 広い allowedDomains ワイルドカードが許可する場合でも特定ドメインをブロックする |
sandbox.filesystem設定と permission ルールのパスは統合されて最終的なサンドボックス設定になる/sandboxは permission mode ではない。permission mode はツール呼び出しが動くか・先にプロンプトを出すかを決め、サンドボックスは動き始めた Bash コマンドが何にアクセスできるかを制限する- サンドボックスの auto-allow モードと auto mode は別物で、独立して動き併用できる
設定
{
"sandbox": {
"enabled": true,
"filesystem": {
"allowWrite": ["~/.kube", "/tmp/build"]
}
}
}
{
"sandbox": {
"enabled": true,
"filesystem": {
"denyRead": ["~/"],
"allowRead": ["."]
}
}
}
{
"sandbox": {
"enabled": true,
"credentials": {
"files": [
{ "path": "~/.aws/credentials", "mode": "deny" },
{ "path": "~/.ssh", "mode": "deny" }
],
"envVars": [
{ "name": "GITHUB_TOKEN", "mode": "deny" },
{ "name": "NPM_TOKEN", "mode": "deny" }
]
}
}
}
{
"sandbox": {
"enabled": true,
"network": {
"tlsTerminate": {},
"allowedDomains": ["*.github.com", "registry.npmjs.org"]
},
"credentials": {
"envVars": [
{ "name": "GH_TOKEN", "mode": "mask", "injectHosts": ["api.github.com"] },
{ "name": "NPM_TOKEN", "mode": "mask" }
]
}
}
}
制約・注意点
トラブルシューティング
- host-not-allowed エラー: プロンプトで許可するとホストが許可リストに追加され、以降はサンドボックス内で動く
jestがハングまたは失敗する:watchmanはサンドボックスと非互換。jest --no-watchmanを使う- macOS で Go 製 CLI が TLS 検証に失敗する:
gh/gcloud/terraformなどは Seatbelt 下で TLS 検証に失敗しうる。excludedCommandsに列挙してサンドボックス外で動かす。httpProxyPortで MITM プロキシとカスタム CA を使っている場合は代わりにenableWeakerNetworkIsolationをtrueにする - macOS で
open/osascript/ ブラウザ認証フローがエラー-600で失敗する: サンドボックスは既定で Apple Events をブロックする。allowAppleEventsを user / managed / CLI settings でtrueにする(project settings では無視される)。有効にするとコード実行の分離が失われる。代わりにexcludedCommandsに追加する方法もある dockerが失敗する:dockerはサンドボックスと非互換。docker *をexcludedCommandsに追加する- コンテナ内で bubblewrap が起動しない: 非特権コンテナでは新しい
/procをマウントできない。enableWeakerNestedSandboxをtrueにするとコンテナ既存の/procを bind-mount する。外側のコンテナが十分な分離境界を提供している場合にのみ使う - root で
--dangerously-skip-permissionsが失敗する: Linux と macOS では root / sudo でこのフラグがブロックされる。認識されたサンドボックス内では自動でスキップされる
セキュリティ上の限界
- ネットワークフィルタリング: 既定では組み込みプロキシは TLS を終端・検査しないため、暗号化された接続の内容は検査されない。
network.tlsTerminateは mask のための TLS 終端であり、コンテンツフィルタリングを追加しない github.comのような広いドメインの許可はデータ持ち出しの経路を作りうる。プロキシはクライアントが指定したホスト名で許可を判断するため、domain fronting などで allowlist 外のホストに到達されうる- Unix socket による権限昇格:
allowUnixSocketsの設定は強力なシステムサービスへのアクセスを与えうる(例:/var/run/docker.sockの許可は Docker socket 経由でホストへのアクセスを与える) - ファイルシステム権限による昇格:
$PATH上の実行ファイルを含むディレクトリ、システム設定ディレクトリ、.bashrc/.zshrcなどへの書き込み許可はコード実行につながりうる - Linux サンドボックスの強度:
enableWeakerNestedSandboxモードはセキュリティを大きく弱める。他の分離が別途強制されている場合にのみ使う - 設定ファイルの保護: サンドボックスは、サンドボックス化コマンドが自分のポリシーを書き換えられるファイルへの書き込みを自動的に拒否する(filesystem isolation を無効にするとこの deny ルールも切れる)
- 全スコープの Claude Code の
settings.jsonと managed settings ディレクトリ - プロジェクトルートの
.mcp.json、および--add-dir//add-dirで追加した各ディレクトリのルートの.mcp.json - 起動後に保護対象の settings ファイルパスに現れた symlink の解決先(次のコマンドから deny リストに追加される)。v2.1.210 より前は symlink を解決していなかった
- 全スコープの Claude Code の
- filesystem isolation を off にして自動承認していると、サンドボックス化コマンドが後続コマンドが実行・読み取りするファイル(シェル起動ファイル、
$PATH上の実行ファイル、~/.claude/settings.json)を書いて自身のアクセスを広げうる
範囲
- 組み込みファイルツール: Read / Edit / Write はサンドボックスを通らず permission system を直接使う
- Computer use: 実際のデスクトップ上で動き、分離環境ではない
- 環境変数: サンドボックス化 Bash コマンドは既定で親プロセスの環境を継承する(そこに設定された認証情報も含む)
- Subagents: subagent は親セッションと同じプロセスで動き、同じサンドボックス設定を使う。親セッションでサンドボックスが有効なら subagent 内の Bash コマンドもサンドボックス化される
- パフォーマンスオーバーヘッドは最小だが、一部のファイルシステム操作はやや遅くなりうる
関連
facts/claude-code/permissions.mdfacts/claude-code/permission-modes.mdfacts/claude-code/settings.mdfacts/claude-code/security.mdfacts/claude-code/env-vars.mdfacts/claude-code/sub-agents.mdfacts/claude-code/tools-reference.mdfacts/claude-code/worktrees.md