サンドボックスバックエンド
バックエンドの概要
「バックエンドの概要」というセクション| バックエンド | 値 | プラットフォーム | 可用性 |
|---|---|---|---|
| 閉じ込め VM | microvm |
macOS、Linux、Windows(microVM ハイパーバイザー) | microVM ランタイムを対象にプローブでゲートされます。対話ターミナルに適用されます — シェルはホスト上ではなく リグ の内部で動作します |
| ネイティブ | native |
macOS(Seatbelt)、Linux と WSL2(bubblewrap) | 起動時にプローブされます。Linux では、bubblewrap が強制できないファイル名 glob の書き込み拒否を必要とする実行を拒否します |
| なし | none |
すべて | パース時のデフォルト、ターミナルのデフォルトであり、利用できるバックエンドがない場合、または --sandbox off が設定されている場合のフォールバックです |
SandboxBackend.fromName は、保存された値が null または認識できない場合に none を返します。保存された "docker" は native にマップされます。
microvm はカーネル境界を持つ唯一のバックエンドです — ワークロードは
本当にホスト上では動作しません。どちらの方向でも暗黙のフォールバックには
なりません。VM を起動できないホストで明示的に要求すると明確に失敗します
(「VM を要求したのに手元のノート PC が返ってきた」は、エンクロージャーが
許容できない唯一の劣化です)。そして native に降格するのは指定されていない
デフォルトだけであり、その旨がログ行に出力されます。セッションの実際の
バックエンドはクライアントに報告されてバッジ表示されるため、ターミナルが
ホスト上で動作しながら閉じ込められていると主張することは決してできません。
VM 自体のライフサイクル、イメージ、エグレスについては、リグのリファレンスで説明しています。
Windows にはネイティブサンドボックスがありません。 NativeSandboxAdapter.probe は、macOS または Linux/WSL2 以外のすべてのホストで available: false を返します。したがって Windows ではエージェントのディスパッチは none を使います。microvm バックエンドは別系統です。microVM ランタイムを対象にプローブでゲートされ、ホスト上の bash のラップではなく、対話ターミナルとリグに適用されます。
プローブの結果
「プローブの結果」というセクション強制をゲートするのはプローブです。プローブはサーバーの起動時に一度だけ実行されます。
| ホスト | available |
注記 / ヒント |
|---|---|---|
| macOS | true |
sandbox-exec(Seatbelt) — 名前空間の分離であり、カーネル境界はありません |
bwrap と socat のある Linux または WSL2 |
true |
bubblewrap — 名前空間の分離であり、カーネル境界はありません |
| いずれかのツールを欠く Linux または WSL2 | false |
requiresInstall: true、不足しているパッケージを名指しするインストールのヒント付き |
| その他のプラットフォーム | false |
このプラットフォームではネイティブサンドボックスは提供されません |
サーバーは結果を起動時の 1 行でログに記録します。agent sandbox ON とその注記、no OS-native agent sandbox on this host とそのヒント、または agent sandbox DISABLED by --sandbox off のいずれかです。GET /healthz にサンドボックスのフィールドはありません。
--sandbox / CC_SERVER_SANDBOX は on(デフォルト)または off を受け付けます。これは有効化ではなくオプトアウトです。on は「ホストがバックエンドを提供する場合にラップする」という意味であり、決して「バックエンドを必須にする」という意味ではありません。
ネイティブバックエンド
「ネイティブバックエンド」というセクションmacOS: Seatbelt
「macOS: Seatbelt」というセクションApple の Seatbelt サンドボックス機構(macOS App Sandbox が使うのと同じシステム)を使用します。
生成されるプロファイルはデフォルトで許可((allow default))であり、そこから拒否を切り出します。完全なデフォルト拒否のプロファイルでは対話シェルが使えなくなるからです — 列挙するには dyld、XPC、Mach の呼び出しが多すぎます。実際上の結果として、エージェントは依然としてホストのほとんどを読み取れます。登録済みのチェックアウトは、不可視化によってではなく、明示的な書き込みと名前変更の拒否によって保護されます。
- ファイルシステムの読み取り: シークレットパス(
~/.ssh、~/.aws、~/.gnupg、~/.config/gh、~/Library/Keychains、および読み取り拒否セットの残り)は拒否されます - ファイルシステムの書き込み: 拒否にリセットしてから、明示的なサブパスの許可を加えます。必須拒否パス(シェルの rc ファイル、
.git/hooks、Claude の設定、保護されたチェックアウト)は、書き込み可能なルートの内部であってもブロックされます。file-write-unlinkは、すべての拒否パスとその祖先で拒否されるため、名前変更で書き込み拒否を回避することはできません - プロセス:
process-execは常に危険なバイナリを拒否し、さらに書き込み可能なディレクトリからの実行をブロックします - ネットワーク: インプロセスのプロキシポートと DNS に制限されます — ループバックが一律で許可されることはなく、Unix ソケットも許可されません。プロキシがセッションごとのドメイン許可リストを強制します(ネットワークエグレス を参照)
- 構成: プロファイルは起動ごとに
SandboxSpecから生成されます
要件:
sandbox-exec(/usr/bin/sandbox-exec)。すべての macOS インストールに含まれます — 追加のツールは不要です
Linux: bubblewrap
「Linux: bubblewrap」というセクションbubblewrap(bwrap)を使ってマウント名前空間と PID 名前空間を作成します。
- ファイルシステム: バインドされたパスだけが見えるマウント名前空間を作成します
- ネットワーク: 共有されていないネットワーク名前空間で動作します。トラフィックは
socatの Unix ソケットブリッジを通ってホストのプロキシに到達します - プロセス: PID 名前空間の分離
要件:
bubblewrapとsocatがインストールされていること(Debian/Ubuntu ではsudo apt-get install bubblewrap socat)- カーネルの名前空間サポート(現代の Linux では標準)
bubblewrap は既存のパスを覆い隠すことはできますが、書き込み可能なバインドの内部で新しい .env、
*.key、*.pem ファイルを禁止することはできません。標準のディスパッチポリシーは
これらのファイル名 glob の拒否を要求するため、現在ネイティブのエージェント
ディスパッチは、プローブが bubblewrap を見つけた場合でも Linux/WSL2 では
フェイルクローズドします。黙って弱められたポリシーで動作することはありません。
Linux のネイティブディスパッチを復活させるには、作成時のファイル名ルールを
備えたバックエンドが必要です。サンドボックス化を無効にするのは、明示的な
非閉じ込めのオプトアウトであり、同等の回避策ではありません。
なしバックエンド
「なしバックエンド」というセクションサンドボックス化はありません。プロセスはホスト上で直接動作し、ホストのファイルシステム、ネットワーク、プロセスへのアクセスを持ちます。ACP とハーネスの bash ツールには依然として環境のサニタイズとコマンドポリシーが適用されます。NoSandboxAdapter 経由の Claude Code はホストの環境を継承します。これは、利用できるバックエンドがないホスト、または --sandbox off のホストでエージェントのディスパッチがフォールバックする先であり、クライアントが何も指定しない場合のターミナルのデフォルトでもあります。
サーバーがホストするターミナル
「サーバーがホストするターミナル」というセクションターミナルは、ディスパッチのプローブによってではなく、独自の条件でサンドボックス化されます。TerminalSessionService の defaultBackend は none であり、cc_server はそれを上書きしないため、クライアントが明示的に native を要求しない限り、ターミナルセッションはホストのシェルを実行します — デスクトップのターミナルパネルは要求しません。
native が要求されると、シェルは固定のターミナルプロファイルの下で SandboxManager を通じてラップされます。$HOME とセッションの作業ディレクトリは書き込み可能で、ネットワークは開いており、~/.ssh、~/.aws、~/.gnupg、~/.config/gh、~/Library/Keychains は読み取り拒否です。読み取り専用のフォージトークンとプッシュのゲートウェイは適用されません — それらはディスパッチの関心事です。ラップがサポートされていない場合、セッションは、ホストシェルの PTY にネイティブのバッジを表示するのではなく、失敗します。
ネットワークエグレス
「ネットワークエグレス」というセクションサンドボックスが起動されると、外向きのネットワークアクセスはカーネルのファイアウォールルールではなく、インプロセスのプロキシによって強制されます。利用できるバックエンドがないホストでは、これらいずれも当てはまらず、スポーンされたプロセスはサーバーユーザーとまったく同じようにネットワークに到達します。
- サンドボックスランタイムは、
cc_serverプロセス内の127.0.0.1で HTTP/HTTPS プロキシと SOCKS5 プロキシを実行します。制限付きセッションごとに 1 組です(http_proxy.dart、socks_proxy.dart)。同時に動作する実行が 1 組のペアを共有することはありません。 - サンドボックス化されたプロセスはプロキシの環境変数を受け取ります(
HTTP_PROXY/HTTPS_PROXY→ HTTP プロキシ、ALL_PROXY→ SOCKS プロキシ。GIT_SSH_COMMANDは git-over-SSH を SOCKS プロキシ経由にルーティングします)。Linux ではネットワーク名前空間が共有されていないため、プロキシが唯一の出口です。macOS ではサンドボックスがホストのループバックを共有し、プロキシと直接通信します。 - 各接続のターゲットホストはセッションのドメイン許可リストと照合されます。それ以外は拒否されます。ワイルドカードの形式は 2 つあり、いずれも
*はちょうど 1 つです。先頭の*.example.comは任意のサブドメイン(a.b.example.comを含む)に一致しますが、頂点ドメイン自体には一致しません。中間ラベルのbedrock.*.amazonaws.comはちょうど 1 つのラベルに一致します(bedrock.us-east-1.amazonaws.comには一致しますが、bedrock.evil.attacker.amazonaws.comには一致しません)。 - 許可リストは、セッションごとに、厳選されたベースライン(
kBaselineAllowedDomains: LLM プロバイダー、Git ホスティング、パッケージレジストリ)、GitHub のドメイン(kGithubDomains)、さらにSandboxSpec.egressAllowlistから解決されます。ディスパッチ経路は追加のegressAllowlistエントリを決して渡さないため、実際にはすべての実行がベースラインと GitHub を取得します。 - 固定の拒否リスト(
kBaselineDeniedDomains: クラウドメタデータのエンドポイント、テレメトリの送信先)は、すべての許可より優先されます。 networkEnabled: falseでも、セッションごとのプロキシは起動しますが、許可リストが空であるため、外向きの接続はすべて拒否されます。ディスパッチは実行の開始時にネットワークにアクセスのルールからこの値を設定します: 拒否はネットワークをオフにし、許可と先に確認はオンのままにします。
SandboxSpec
「SandboxSpec」というセクションSandboxPort.launch に渡される仕様:
| フィールド | 型 | 説明 |
|---|---|---|
sessionId |
String |
安定したセッション識別子(通常はスペース id) |
workspaceId |
String |
所有するワークスペースの id |
agentId |
String? |
現在サンドボックスにバインドされているエージェント(存在する場合) |
bindMounts |
List<SandboxBindMount> |
ホスト→ゲストのマウント。サンドボックスはここに列挙されたホストパスだけを見ます |
networkEnabled |
bool(デフォルト true) |
ディスパッチ時にネットワークエグレスのルールから設定されます(拒否に解決された場合にのみオフ)。オフの場合、セッションごとのプロキシは起動しますが、許可リストが空であるため、外向きの接続はすべて拒否されます |
egressAllowlist |
List<String>(デフォルト []) |
追加で許可するエグレスドメイン。ワイルドカードをサポートします(*.example.com、および 1 ラベルの中間形式)。ディスパッチがこれを設定することはないため、ラップされた実行は厳選されたベースラインと GitHub ドメインを取得します |
guestWorkdir |
String? |
サンドボックス内のデフォルトの作業ディレクトリ。個々の exec 呼び出しで上書きできます |
mode |
Mode(デフォルト chat) |
ファイルシステムの書き込みルールを切り出します。chat はバインドマウントを書き込み可能に保ち、review、plan、orchestrate は読み取り専用です |
protectedPaths |
List<String>(デフォルト []) |
どのモードでも、サンドボックス内で決して書き込み可能にしてはならないホストパス |
runnerStateDirs |
List<String>(デフォルト []) |
ランナーが自身の状態を保持するホストディレクトリ。どのモードでも書き込み可能です(現在は Control Center が管理する CLAUDE_CONFIG_DIR です) |
execGrantRoots |
List<String>(デフォルト []) |
macOS で書き込み可能ディレクトリの exec ブロックを再び開く、オペレーターが承認したディレクトリツリー。Linux では無視されます — bwrap には再度開くべき $HOME の exec ブロックがありません |
protectedPaths は、登録済みの元のリポジトリチェックアウトを保持し、ディスパッチごとにワークスペースのリポジトリから解決されます。エージェントは会話ごとのコピーオンライトのワークツリーでのみ作業するため、元のチェックアウトはサンドボックス内から決して書き込み可能にしてはなりません — macOS では、そうしなければ Seatbelt の $HOME への一律の書き込み許可により、bash 経由でそれらが書き込み可能なままになってしまいます。これらは chat を含むどのモードでも、シークレットの書き込み拒否セットに加わります。
すべての読み取り拒否パスと書き込み拒否パスは、その文字どおりの綴りと、シンボリックリンクを解決した綴りの両方で出力されます。カーネルは拒否ルールを解決後のパスと照合するため、シンボリックリンクのパスに対して書かれたルールは決して発動しません — そして macOS では、/tmp が /private/tmp に、/var/folders/… が /private/var/folders/… に解決されるため、これは例外的なケースではなく一般的なケースです。* または ? を含むエントリは glob として扱われ、そのままにされます。解決できないパスは書かれたまま保持されます。
SandboxBindMount
「SandboxBindMount」というセクション| フィールド | 型 | 説明 |
|---|---|---|
hostPath |
String |
ホスト上の絶対パス |
guestPath |
String |
サンドボックス内のパス(ネイティブサンドボックスでは hostPath と等しくなります。アダプターの対称性のために保持されています) |
readOnly |
bool(デフォルト false) |
true の場合は読み取り専用でマウントします |
SandboxHandle
「SandboxHandle」というセクションSandboxPort.launch が返す値:
| フィールド | 型 | 説明 |
|---|---|---|
sessionId |
String |
セッション識別子 |
backend |
SandboxBackend |
実行中のバックエンド |
state |
SandboxState |
ライフサイクルの状態 |
error |
Object? |
state が error のときに設定されます |
details |
Map<String, Object?> |
アダプター固有の管理情報(作業ディレクトリ、PID、プロファイルパスなど) |
SandboxState
「SandboxState」というセクション| 状態 | 説明 |
|---|---|
created |
仕様は作成されましたが、VM はまだ起動していません |
warm |
実行中で、コマンドを exec する準備ができています |
active |
現在コマンドを実行しています |
suspended |
RAM を節約するために一時停止され、ディスクにチェックポイントされています |
destroyed |
破棄済み。ハンドルはもう有効ではありません |
error |
起動に失敗しました — SandboxHandle.error を参照してください |
サンドボックスイベント
「サンドボックスイベント」というセクション| イベントの種類 | 説明 |
|---|---|
stdout |
サンドボックスからの標準出力 |
stderr |
サンドボックスからの標準エラー |
exit |
サンドボックスのプロセスが終了しました(exitCode を保持します) |
starting |
サンドボックスが起動中です |
ready |
サンドボックスが exec 呼び出しを受け付けられる状態です |
killed |
プロセスがホストによって強制終了されました(OOM、タイムアウト、手動停止) |
violation |
サンドボックスポリシーに違反しました(SandboxViolation を保持します) |
SandboxViolation
「SandboxViolation」というセクション| フィールド | 型 | 説明 |
|---|---|---|
action |
String |
拒否された動詞(例: file-read*、network-outbound) |
target |
String |
拒否された操作の対象であったパスまたはホスト |
raw |
String? |
生のログ行。デバッグに役立ちます |
関連項目
「関連項目」というセクション- サンドボックスとセキュリティ
- サンドボックスポリシー
- ガードレール
- cc_server CLI:
--sandboxフラグ