この記事の目次
Claude Codeのサンドボックス(sandbox)は、Claudeが実行するシェルコマンドとその子プロセスに対して、触れるファイルと届く通信先をOSが制限する仕組みです。既定ではオフで、セッション内で /sandbox を実行するか、設定ファイルで sandbox.enabled を true にすると有効になります。有効にしたら、Claudeに touch ~/sandbox-probe を実行させ、macOSなら Operation not permitted、LinuxとWSL2なら Read-only file system で失敗することを確かめます。
この記事は、公式ドキュメント Configure the sandboxed Bash tool の記述だけに基づいています。Claude Codeの実行環境をコンテナにする方法はClaude CodeをDockerで動かす方法、権限モードの違いは権限モードの解説、settings.jsonの置き場所と優先順位はsettings.jsonの解説を参照してください。
Claude Codeのサンドボックス(sandbox)は何を制限するのか
制限の対象は、Bash、PowerShell、Monitorのコマンドと、そこから起動されるプロセスです。OSがコマンドの実行中に制限をかけるため、sandbox内のコマンドは1件ずつ権限確認なしでも実行させられます。実装はmacOSがSeatbelt、LinuxとWSL2がbubblewrapで、基盤はオープンソースの @anthropic-ai/sandbox-runtime です。
有効化した直後の設定の既定値は次のとおりです。
| 対象 | 既定の範囲 | 変更する設定 |
|---|---|---|
| 書き込み | 作業ディレクトリ、ユーザーごとの一時ディレクトリ、追加したディレクトリ。保護パスは書き込み拒否のまま | filesystem.allowWrite / filesystem.denyWrite |
| 読み取り | マシンの大半。~/.ssh や ~/.aws/credentials も読める |
filesystem.denyRead / credentials |
| 通信 | 直接の経路なし。ローカルのプロキシが許可ドメインと照合し、許可ドメインは空から始まる | network.allowedDomains / network.deniedDomains |
| 環境変数 | Claude Codeから継承し、環境内の秘密も含む | credentials |
サンドボックスで見落としやすいのは読み取りと環境変数です。既定のままでは認証情報のファイルも環境変数のトークンも読めます。公式は組み込みの拒否リストはないと明記しているため、守りたいものは自分で列挙します(後述)。
sandboxの外で動くもの
sandboxが包むのはシェルコマンドだけです。次のものは対象外です。
- Read、Edit、Write、WebFetch、WebSearchなどの組み込みツール。これらは権限ルールに従います。
denyReadはReadツールを止めず、allowedDomainsはWebFetchを制限しません - フック、ローカルのMCPサーバー、プラグインのモニター、LSPサーバー、ステータスラインや
apiKeyHelperなどの補助コマンド。これらはフルアクセスで動きます - 自分が
!のシェルモードで打ったコマンド(多くのセッションでsandbox外) excludedCommandsに一致するコマンドと、Claudeが求めるsandbox外での再実行
これらまで1つの境界に入れたい場合、公式はClaude Codeのプロセス自体をコンテナ、仮想マシン、sandbox runtimeで動かす方法を案内しています。なお、サブエージェントは親セッションと同じsandbox設定を使います。権限ルール側の設計はセキュリティ設定の解説が扱います。
/sandboxで有効にする手順は?
macOSは追加の導入なしで始められます。LinuxとWSL2は bubblewrap と socat が必要です。Ubuntu/Debianでは次のコマンドで入れます。
sudo apt-get install bubblewrap socat
Fedoraでは次のとおりです。
sudo dnf install bubblewrap socat
依存の確認は起動時に行われるため、導入後はClaude Codeを再起動してから進めます。手順は3つです。
- セッションで
/sandboxを実行し、パネルを開く。Mode、Overrides、Configの3タブが出る - Modeタブで「auto-allow」か「regular permissions」を選ぶ(選び方は次の節)
- ビルドやテストなどのコマンドをClaudeに実行させる。新しいドメインへの通信が初めて必要になると承認を求められる
パネルで選んだモードは、そのプロジェクトの .claude/settings.local.json に保存されます。全プロジェクトで有効にするなら、~/.claude/settings.json で sandbox.enabled を true にします。設定ファイルを書き換えずに1セッションだけ試すなら、公式の例どおり --settings で渡せます。
claude --settings '{"sandbox": {"enabled": true, "allowUnsandboxedCommands": false}}'
OS別に詰まりやすい点
- パネルにDependenciesタブしか出ない: 必須パッケージが不足しています。導入して再起動し、
/sandboxを再実行します - Ubuntu 24.04以降: 既定のAppArmorポリシーがbubblewrapのuser namespace作成を妨げます。
sysctl kernel.apparmor_restrict_unprivileged_usernsが1を返す場合は、公式ページのAppArmorプロファイルを追加します。0なら不要です - WSL1:
Sandboxing requires WSL2と表示されます。WSL2へ上げるか、sandboxなしでClaude Codeを使います - ネイティブWindows: sandboxは動かず、コマンドはsandboxなしで実行されます。使うならWSL2の中でClaude Codeを動かします。導入経路はWindows版の導入ガイドにあります
もう1つ重要な既定動作があります。依存が足りない、またはOSが非対応でsandboxを起動できないとき、Claude Codeはsandboxなしでコマンドを実行します。sandboxが動かないなら起動自体を止めたい場合は、sandbox.failIfUnavailable を true にします。
auto-allowとregular permissions、どちらを選ぶか
2つのモードは、ファイル操作と通信の制限内容が同じです。違いはsandbox内のコマンドを自動で承認するかどうかだけです。
| モード | sandbox内のコマンド | 向いている場面 |
|---|---|---|
| auto-allow | 確認なしで実行 | 書き込み先と通信先を決め終え、承認の多さを減らしたい |
| regular permissions | sandbox内でも通常の承認を通る | まず制限の効き方を見ながら慣らしたい |
auto-allowが有効だと、Manualモードでも、sandbox内でファイルを書き換えるBashコマンドは確認なしで実行されます。一方で、Bashのdenyルールに一致するコマンドはブロックされ、Bash(git push *) のような内容指定のaskルールは確認を求めます。また、コマンドに一致するallowルールは、そのコマンドのsandbox外での再実行も承認してしまう点に注意します。
sandbox外での再実行を止める(Strict sandbox mode)
sandbox内で失敗したコマンドを、Claudeが dangerouslyDisableSandbox パラメータ付きで再実行しようとすることがあります。Manualモードでは「Bash command (unsandboxed)」という確認が出ますが、bypassPermissions モードでは確認なしで実行されます。
この逃げ道を閉じるには、sandbox設定で "allowUnsandboxedCommands": false にします。/sandbox のOverridesタブではStrict sandbox modeとして表示されます。無効にするとClaude Codeは dangerouslyDisableSandbox を無視し、sandboxが動いている間は、excludedCommands に一致しないコマンドはsandbox内で動きます。ユーザー設定、--settings、managed settingsに書いた false は、プロジェクト設定が true でも保たれます。ただしv2.1.285より前は、プロジェクトの true がユーザー設定の false より優先されていました。
書き込み先と読み取り制限はどう設定するか
kubectl、terraform、npm などが作業ディレクトリの外に書き込む必要があるときは、sandbox.filesystem.allowWrite に特定のパスだけを足します。書き込みを広げる前に、対象から外すパスを決めておきます。公式は、$PATH 上の実行ファイルがあるディレクトリ、システムの設定ディレクトリ、.bashrc や .zshrc などのシェル設定ファイルへの書き込みを許すと、他のユーザーやシステムのプロセスがそれらを使うときに別の文脈でのコード実行につながりうると警告しています。公式の例です。
{
"sandbox": {
"enabled": true,
"filesystem": {
"allowWrite": ["~/.kube", "/tmp/build"]
}
}
}
公式は、ツールを excludedCommands で丸ごとsandbox外に出すより、この方法を推奨しています。パスは /tmp/build のように / から始めればルートからの指定、~/.kube ならホーム相対です。Read/Editの権限ルールで使う //path の書き方とは違います。同じ配列を複数のスコープで定義すると、置き換えではなくマージされます。
読み取りは denyRead で塞ぎ、allowRead で一部を開け直せます。ルールが重なった場合は、より狭いパスのルールが優先されます。次の例はホームディレクトリ全体の読み取りを禁じ、プロジェクトだけ読めるようにするものです。
{
"sandbox": {
"enabled": true,
"filesystem": {
"denyRead": ["~/"],
"allowRead": ["."]
}
}
}
この設定はプロジェクトの .claude/settings.json に置きます。~/.claude/settings.json に置くと . が ~/.claude を指すため、プロジェクトのファイルまで読めなくなります。
許可しても書き込めない保護パス
書き込み可能な範囲の中でも、Claude Codeが設定やコードを読み込むファイルへの書き込みは拒否されます。作業ディレクトリの .bashrc、.zshrc、.gitconfig、.vscode、.idea、.git 内の hooks と config などが該当します。allowWrite でもEditのallowルールでも外せません。対象パスの大半は、/sandbox のConfigタブの「Denied within allowed」で確認できます。
認証情報を読ませない
認証情報は sandbox.credentials にまとめて書くのが公式の方法です。"mode": "deny" のファイルは読み取りが拒否され、環境変数は各コマンドの実行前に消されます。公式の例です。
{
"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" }
]
}
}
}
denyのエントリは全スコープからマージされ、どのスコープからも取り消せません。サンドボックスで値を隠したまま認証だけ通す mask モードもありますが、TLS終端などの追加設定が要るため、ここでは扱いません。
通信先はどう許可するか
許可ドメインは空から始まります。未許可のホストへの接続が起きたときの扱いは権限モードで変わり、ManualモードとacceptEditsモードでは確認が出て、dontAsk モードでは拒否されます。bypassPermissions モードでは確認なしで許可されます。ただし strictAllowlist か allowManagedDomainsOnly がオンなら、どの権限モードでも拒否されます。確認で「Yes」を選ぶとそのセッションの間だけ許可され、「Yes, and don’t ask again」を選ぶとローカル設定に WebFetch(domain:...) のallowルールが保存されて次回以降も許可されます。
確認を出したくない定番の通信先は、allowedDomains に先に書いておきます。
{
"sandbox": {
"enabled": true,
"network": {
"allowedDomains": ["github.com", "*.npmjs.org"]
}
}
}
ポートを書かないエントリは、そのホストの全ポートを許可します。deniedDomains に入れたホストは、どの権限モードでも拒否されます。許可リスト外を確認なしで一律に拒否したい場合は、ユーザー設定などで strictAllowlist を true にします。リポジトリの .claude/settings.json に書いても効きません。
許可しても届かない通信
curl、npm、HTTPS経由の git のようにプロキシ用の環境変数を読むツールは、ホストを許可すれば接続できます。一方、素の ssh や多くのデータベースドライバのようにプロキシ変数を無視するツールは、許可したホストにも接続できません。UDP、QUICのHTTP/3、ping などのICMPも外に出られません。
許可の範囲そのものにも注意が要ります。公式は、github.com のような広いドメインの許可がデータ持ち出しの経路になりうると警告しています。既定のプロキシはTLSを終端・検査しないため、暗号化された通信の中身までは見ていません。許可は作業に必要なドメインに絞ります。
sandboxが効いているかを確認するには
公式の確認方法は、次の2つのコマンドを「Claudeに」実行させることです。! で自分が打つとsandbox外で動くことが多く、確認になりません。
touch ~/sandbox-probe
curl --noproxy '*' https://example.com
| コマンド | sandbox内での期待結果 |
|---|---|
touch ~/sandbox-probe |
macOSでは Operation not permitted、LinuxとWSL2では Read-only file system で失敗 |
curl --noproxy '*' https://example.com |
プロキシを迂回する経路がないため Could not resolve host で失敗 |
想定と違ったときの進め方も公式に書かれています。Claudeがsandbox外での再実行を求めてきたら断ります。touch が成功してしまい、ホームディレクトリを書き込み許可にしていないなら、~/sandbox-probe を消してから /sandbox を開き、sandboxがオンか、依存が揃っているかを確認します。前述のとおり、依存が足りないとsandboxなしで実行される点は原因の候補になります。
sandboxで動かないコマンドはどう切り分けるか
コマンド切り分けではまず失敗の出方を見ます。プロキシを使うツールが未許可ホストに当たった場合は、承認の確認が出るか、プロキシから 403 が返ります。sandboxではプロキシを使わないツールの場合は、macOSで Operation not permitted や Could not resolve host、LinuxとWSL2で Network is unreachable や Temporary failure in name resolution のような、ネットワークや名前解決のエラーに見えます。
公式のトラブルシューティングにある症状を表にまとめます。
| 症状 | 原因 | 公式の対処 |
|---|---|---|
| host-not-allowedのエラー | 通信先が許可されていない | 確認で承認するか allowedDomains に追加。allowManagedDomainsOnly で固定されていれば管理者に依頼 |
jest が止まる、失敗する |
watchman がsandboxと非互換 |
jest --no-watchman で実行 |
docker が失敗する |
docker がsandboxと非互換 |
excludedCommands に docker compose * のような狭いパターンを追加 |
macOSで gh、gcloud、terraform がTLS検証に失敗 |
Seatbelt下で失敗することがある | excludedCommands に gh * などツールごとに追加 |
macOSでSSHリモートへの git fetch / pull / push が失敗 |
macOSのトンネルがプロキシに認証できない | リモートをHTTPSに切り替える。SSHを残すなら git のネットワーク系コマンドを excludedCommands に追加 |
| DBクライアントなどが許可ホストに届かない | プロキシ変数を無視するツール | そのコマンドを excludedCommands で外し、askルールで毎回承認 |
| localhostのサーバーに届かない | 既定では直接接続できない | macOSは network.allowLocalBinding を true。LinuxとWSL2では効かないため excludedCommands |
git merge / git checkout が unable to unlink old |
書き込み拒否のファイルを置き換えようとした | 保護パス、denyWrite、書き込み範囲外のどれに当たるかを確認 |
/sandbox が Sandbox settings are overridden by a higher-priority configuration |
managed settingsや --settings が上位で値を決めている |
/status の Setting sources 行で設定元を確認 |
macOSでSSHのリモートをHTTPSに切り替える公式のコマンドは次のとおりです(URLは自分のリポジトリに置き換えます)。
git remote set-url origin https://git.example.com/example-org/example-repo.git
excludedCommandsを書くときの注意
excludedCommands に一致したコマンドは、ファイル制限もプロキシもない状態で、自分と同じ権限で動きます。書くときは次の点を押さえます。
- 引数付きも対象にするならパターンを
*で終える。dockerは引数なしのdockerにしか一致しない - 連結したコマンドは全部が一致しないとsandbox内に残る。リダイレクト、
cd、$(...)を含む呼び出しも同じ docker *のような広いパターンは、そのツールができることすべてをsandbox外に出す
一致しているかは、Manualモードで docker compose up -d のような変更を伴うコマンドを実行させ、「Bash command (unsandboxed)」の確認が出るかで判断できます。足りないのが1つのディレクトリや1つのホストだけなら、allowWrite や allowedDomains で足す方がsandboxの中に残せます。
sandboxに任せきれない部分と、公式で確認すべき点
公式はsandboxを、リスクを下げるが完全な隔離境界ではないものと位置づけています。効果にはファイルと通信の両方の隔離が必要で、既定を広げるときは、allowWrite のパス、広い allowedDomains、excludedCommands の例外が、反対側の制限を崩していないかを確認するよう求めています。たとえば $PATH 上の実行ファイルがあるディレクトリや .bashrc への書き込みを広く許すと、別の文脈でのコード実行につながりえます。
設定キーには、Claude Codeの特定のバージョン以降で使えるものがあります(例: strictAllowlist はv2.1.219以降)。この記事は2026年10月19日に公式ページと照合した内容に基づくため、設定が効かないときは、使っているClaude Codeのバージョンと公式のsandboxingページの要件を照らし合わせてください。一般的なエラーの切り分けはエラー対処の解説にまとめています。