コンテンツにスキップ

サンドボックスバックエンド

バックエンド 値 プラットフォーム 可用性
閉じ込め 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 は「ホストがバックエンドを提供する場合にラップする」という意味であり、決して「バックエンドを必須にする」という意味ではありません。

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 インストールに含まれます — 追加のツールは不要です

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 でも、セッションごとのプロキシは起動しますが、許可リストが空であるため、外向きの接続はすべて拒否されます。ディスパッチは実行の開始時にネットワークにアクセスのルールからこの値を設定します: 拒否はネットワークをオフにし、許可と先に確認はオンのままにします。

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 として扱われ、そのままにされます。解決できないパスは書かれたまま保持されます。

フィールド 型 説明
hostPath String ホスト上の絶対パス
guestPath String サンドボックス内のパス(ネイティブサンドボックスでは hostPath と等しくなります。アダプターの対称性のために保持されています)
readOnly bool(デフォルト false) true の場合は読み取り専用でマウントします

SandboxPort.launch が返す値:

フィールド 型 説明
sessionId String セッション識別子
backend SandboxBackend 実行中のバックエンド
state SandboxState ライフサイクルの状態
error Object? state が error のときに設定されます
details Map<String, Object?> アダプター固有の管理情報(作業ディレクトリ、PID、プロファイルパスなど)
状態 説明
created 仕様は作成されましたが、VM はまだ起動していません
warm 実行中で、コマンドを exec する準備ができています
active 現在コマンドを実行しています
suspended RAM を節約するために一時停止され、ディスクにチェックポイントされています
destroyed 破棄済み。ハンドルはもう有効ではありません
error 起動に失敗しました — SandboxHandle.error を参照してください
イベントの種類 説明
stdout サンドボックスからの標準出力
stderr サンドボックスからの標準エラー
exit サンドボックスのプロセスが終了しました(exitCode を保持します)
starting サンドボックスが起動中です
ready サンドボックスが exec 呼び出しを受け付けられる状態です
killed プロセスがホストによって強制終了されました(OOM、タイムアウト、手動停止)
violation サンドボックスポリシーに違反しました(SandboxViolation を保持します)
フィールド 型 説明
action String 拒否された動詞(例: file-read*、network-outbound)
target String 拒否された操作の対象であったパスまたはホスト
raw String? 生のログ行。デバッグに役立ちます