factsClaude Codesandboxing

stable4 日前 · 2026-08-09

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_userns1 を返す場合は /etc/apparmor.d/bwrapbwrap 用プロファイルを追加して 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.jsonsandbox.enabledtrue にする

サンドボックスのモード

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 ルールはサンドボックス化されたコマンドでもプロンプトを強制する
  • 素の Bash ask ルール(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.disabledtrue にすると、network isolation を保ったまま filesystem isolation をスキップする
  • 既定は off。macOS / Linux / WSL2 に適用される。v2.1.216 以降が必要
  • サンドボックスは 2 つの独立した層(filesystem isolation と network isolation)を持つ

このキーを設定できる設定ソース:

  • user settings、managed settings、--settings CLI フラグのみ。.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.denyReadcredentials.filesdeny read ブロック強制されない
credentials.envVarsdenymask強制される(環境変数のスクラブは filesystem 層から独立)
credentials.filesmask(mask として適用されたもの)強制される
  • サンドボックス化コマンドはセッション一時ディレクトリではなくシェルの $TMPDIR を継承する。Linux では親シェルで未設定のことが多いため、Claude には Bash ツールのガイダンスで mktemp -d を使うよう伝えられる
  • autoAllowBashIfSandboxed は引き続き既定 true なので、サンドボックス化コマンドはプロンプトなしで動く

network isolation

  • サンドボックス外で動くプロキシサーバーでネットワークアクセスを制御する
  • 既定では事前許可されたドメインは無い。 新しいドメインが必要になると承認を求める。Yes を選ぶとそのホストは現在のセッションの残りで許可され、以降は再プロンプトされない
  • allowedDomains で事前許可するとプロンプトを回避できる。WebFetch の allow ルールもドメインを事前許可する
  • strictAllowlisttrue(user / managed / CLI --settings のみ)にすると、allowlist 外のホストへのアクセスをプロンプトせず拒否する。リポジトリの .claude/settings.json / .claude/settings.local.json で設定しても効果は無い。v2.1.219 以降
  • managed settings で allowManagedDomainsOnly を設定すると、許可外ドメインはプロンプトなしで自動ブロックされ、managed settings の allowedDomainsWebFetch(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.tlsTerminatecredentials.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_IDAWS_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 以降)
    • accessKeyIdVarsecretAccessKeyVar は access key ID と secret key を保持する mask 済み envVars エントリを指す。任意の sessionTokenVar は一時認証情報のセッショントークンを指し、設定すると再署名リクエストに x-amz-security-token として実際のトークンを送る
    • 各変数は extractdecode も無い、値全体を mask する mask エントリでなければならない
    • 再署名は access key ID エントリの injectHosts に列挙したホストで行われる
    • 慣例的な変数のいずれかをペアに書くと自動ペアリングを置き換える

プロキシが再署名できない 3 形式(credentials.sigv4 で形式ごとに passthrough にできる。v2.1.224 以降):

リクエスト形式sigv4 キー理由
aws-chunked streaming uploadsstreamingチャンクごとの署名が seed 署名から連鎖するため、再署名にはボディの書き換えが必要
Presigned URLspresigned署名が URL 自体にあり Authorization ヘッダーが無い
SigV4A asymmetric signaturessigv4a再計算できる共有鍵 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 がそのパスを再開放している場合)では denyerror として扱われる

  • 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.failIfUnavailabletrue にする

ポリシーを広げさせない設定:

  • enabledfailIfUnavailable のような boolean キーは managed の値が使われ、ローカル設定は無視される
  • excludedCommandsallowRead のような配列キーはすべてのスコープからマージされるため、開発者が追記してポリシーを広げられる
  • allowManagedReadPathsOnly を managed settings で true にすると、managed settings の allowRead のみが尊重される。ネットワークドメインを同様に固定するには allowManagedDomainsOnly
  • excludedCommands には managed 専用のロックダウンが無いため、開発者は常にエントリを追記できる。managed の一覧は狭く保つ

カスタムプロキシ:

{
  "sandbox": {
    "network": {
      "httpProxyPort": 8080,
      "socksProxyPort": 8081
    }
  }
}

他のレイヤーとの関係

設定・ルール役割
sandbox.filesystem.allowWrite作業ディレクトリ外のパスへのサブプロセス書き込みを許可する
sandbox.filesystem.denyWrite / denyRead特定パスへのサブプロセスアクセスをブロックする
sandbox.filesystem.allowReaddenyRead 領域内の特定パスの読み取りを再許可する
sandbox.filesystem.disablednetwork isolation を保ったまま filesystem 層を完全に切る(v2.1.216 以降)
Edit allow ルールsandbox.filesystem.allowWrite と同様に特定パスへの書き込みを許可する
Read / Edit deny ルール特定のファイル・ディレクトリへのアクセスをブロックする
WebFetch allow / deny ルールドメインアクセスを制御する
Sandbox allowedDomainsBash コマンドが到達できるドメインを制御する
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 を使っている場合は代わりに enableWeakerNetworkIsolationtrue にする
  • macOS で open / osascript / ブラウザ認証フローがエラー -600 で失敗する: サンドボックスは既定で Apple Events をブロックする。allowAppleEvents を user / managed / CLI settings で true にする(project settings では無視される)。有効にするとコード実行の分離が失われる。代わりに excludedCommands に追加する方法もある
  • docker が失敗する: docker はサンドボックスと非互換。docker *excludedCommands に追加する
  • コンテナ内で bubblewrap が起動しない: 非特権コンテナでは新しい /proc をマウントできない。enableWeakerNestedSandboxtrue にするとコンテナ既存の /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 を解決していなかった
  • filesystem isolation を off にして自動承認していると、サンドボックス化コマンドが後続コマンドが実行・読み取りするファイル(シェル起動ファイル、$PATH 上の実行ファイル、~/.claude/settings.json)を書いて自身のアクセスを広げうる

範囲

  • 組み込みファイルツール: Read / Edit / Write はサンドボックスを通らず permission system を直接使う
  • Computer use: 実際のデスクトップ上で動き、分離環境ではない
  • 環境変数: サンドボックス化 Bash コマンドは既定で親プロセスの環境を継承する(そこに設定された認証情報も含む)
  • Subagents: subagent は親セッションと同じプロセスで動き、同じサンドボックス設定を使う。親セッションでサンドボックスが有効なら subagent 内の Bash コマンドもサンドボックス化される
  • パフォーマンスオーバーヘッドは最小だが、一部のファイルシステム操作はやや遅くなりうる

関連

  • facts/claude-code/permissions.md
  • facts/claude-code/permission-modes.md
  • facts/claude-code/settings.md
  • facts/claude-code/security.md
  • facts/claude-code/env-vars.md
  • facts/claude-code/sub-agents.md
  • facts/claude-code/tools-reference.md
  • facts/claude-code/worktrees.md