Claude Media
Claude Codeをsandbox-runtime(srt)で起動する設定と既定の遮断範囲

Claude Codeをsandbox-runtime(srt)で起動する設定と既定の遮断範囲

sandbox-runtime(srt)でClaude Code全体を包む手順。~/.srt-settings.jsonの書き方、既定で遮断される範囲、Linuxで守れない範囲を解説します。

Claude Codeをsandbox-runtime(srt)で起動する設定と既定の遮断範囲

sandbox-runtime(コマンド名はsrt)は、Claude Codeのプロセス全体をSeatbeltまたはbubblewrapの隔離で包むnpmパッケージです。~/.srt-settings.jsonを先に用意し、npx @anthropic-ai/sandbox-runtime claudeで起動します。設定が無いままでも起動はできますが、ネットワークは遮断され、書き込みも限られた場所にしか通りません。この記事では、必要な設定、起動手順、既定で遮断される範囲、Linuxで守れない範囲を順に説明します。

sandbox-runtimeは組み込みsandboxと何が違うのか

Claude Codeには/sandboxで有効にする組み込みのBashサンドボックスがあります。こちらが制限するのはBash、PowerShell、Monitorのコマンドとその子プロセスです。Read・Edit・WebFetchなどの組み込みツールは、Claude Codeのプロセス内で動くため対象外です。MCPサーバーとコマンドフックも、ホスト上で制約なしに動きます。

sandbox-runtimeは、同じ隔離の仕組みでClaude Code本体を丸ごと包みます。ファイルツール、MCPサーバー、フックまで同じ境界の内側に入る点が違いです。

方式隔離される範囲Dockerの要否
組み込みのBashサンドボックス隔離される範囲Bash・PowerShell・Monitorのコマンドと子プロセスDockerの要否不要
sandbox-runtime隔離される範囲ファイルツール・MCPサーバー・フックを含むプロセス全体Dockerの要否不要
Dev container隔離される範囲開発環境全体Dockerの要否必要

組み込み側の設定はsandbox.enabledとサンドボックス設計の解説にまとめてあります。Dockerで囲う方法はDevContainerの実装記事が扱っています。各方式の比較はAIコーディングエージェントのサンドボックス実装比較にあります。

公式は、--dangerously-skip-permissionsで無人運転するときにこの方式を選択肢の一つに挙げています。権限プロンプトが無い状態では、選んだ隔離境界が唯一の防御になるためです。この場合はrootでなく非rootユーザーで動かします。LinuxとmacOSでは、rootのまま同フラグを付けるとClaude Codeが起動を拒否します。

sandbox-runtimeはベータのリサーチプレビューです。公式は設定形式が今後変わりうると明記しています。

起動前に入れておく依存パッケージ

LinuxとWSL2では、組み込みsandboxと同じbubblewrapとsocatに加え、ripgrepが要ります。Claude Codeはripgrepを同梱していますが、単体のruntimeはPATHから探します。ディストリビューションのパッケージマネージャーで入れてください。

# Ubuntu / Debian の例
sudo apt-get install bubblewrap socat ripgrep

macOSでは、Claude Codeの公式ドキュメントは追加パッケージ不要としています。一方、sandbox-runtimeのREADMEはmacOSの依存にripgrep(brew install ripgrep)を挙げています。禁止パスの検出に使うためです。入れ忘れないよう、macOSでもripgrepを用意しておくと確実です。

Ubuntu 24.04以降では、kernel.apparmor_restrict_unprivileged_usernsが既定で有効です。この設定はネームスペースから権限を剥がすため、READMEは無効化するか、AppArmorのプロファイルで許可するよう案内しています。同じ症状の原因はunshare(CLONE_NEWUSER)の失敗記事でも扱っています。

~/.srt-settings.jsonに何を書くか

設定ファイルの置き場所は~/.srt-settings.jsonです。別の場所に置くなら--settingsで渡します。既定では、ネットワークは全拒否で、書き込みは組み込みのわずかなパスに限られます。Claude Codeを動かすなら、次の許可が最低限要ります。

書き込みを許可する場所:

  • プロジェクトのディレクトリ
  • Claude Codeの設定パスである~/.claudeと~/.claude.json
  • 実行時ファイルの置き場である/tmp

通信を許可するドメイン:

  • api.anthropic.com(サードパーティのプロバイダーを使うなら、そのエンドポイント)
  • claude.aiとplatform.claude.com(OAuthのサインインとトークン更新に使う)

サードパーティのプロバイダーでも、api.anthropic.comは残します。WebFetchのドメイン安全確認が、既定ではこのドメインを呼ぶためです。skipWebFetchPreflight: trueを設定すれば省けます。APIキー認証で動かすなら、claude.aiとplatform.claude.comは外せます。

公式の説明に沿った最小構成の例を示します(設定形式はREADMEの例に準じた形で、プロジェクトの場所は.としています)。

{
  "network": {
    "allowedDomains": [
      "api.anthropic.com",
      "claude.ai",
      "platform.claude.com"
    ]
  },
  "filesystem": {
    "allowWrite": [".", "~/.claude", "~/.claude.json", "/tmp"]
  }
}

社内のパッケージレジストリやGitHubを使う作業では、allowedDomainsにそれらのドメインを足します。*.github.comのようなワイルドカードと、api.example.com:443のようなポート指定が使えます。deniedDomainsは許可リストより先に評価され、優先されます。

allowWriteとdenyWriteの関係は、通常の直感と逆になる場面があります。書き込みはdenyWriteがallowWriteに勝ちます。読み取りは逆で、allowReadがdenyReadに勝ちます。書き込みの調整方法はallowWrite/denyWriteの記事、読ませたくない認証情報の隠し方は認証情報ファイルのmask設定が参考になります。

初回の起動手順とLinuxで先に作っておくもの

LinuxとWSL2のruntimeは、書き込み許可を「すでに存在するパス」にだけ適用します。まっさらな環境では、初回起動の前に設定パスを作っておく必要があります。

mkdir -p ~/.claude && \
  { [ -f ~/.claude.json ] || echo '{}' > ~/.claude.json; }

設定ファイルとパスが揃ったら、npxでClaude Codeを包んで起動します。

npx @anthropic-ai/sandbox-runtime claude

Claude Codeは、設定した境界の内側で立ち上がります。同じ形式のコマンドで、単体のMCPサーバーやほかの補助プロセスも包めます。READMEにはnpm install -g @anthropic-ai/sandbox-runtimeで入れるsrtコマンドの例もあり、srt --settings /path/to/srt-settings.json <コマンド>の形でも使えます。

設定が読めなかったときの挙動

ここが最初に確認したい点です。挙動は、設定ファイルの渡し方で分かれます。

状況runtimeの挙動
~/.srt-settings.jsonが無いruntimeの挙動起動する。ネットワークは遮断、書き込みは/tmp/claudeなどの組み込みパスだけ
--settingsで渡したファイルが読み込めないruntimeの挙動起動を拒否する

公式は「クリーンに起動したことを、設定が読み込まれた証拠と考えない」と注意しています。~/.srt-settings.jsonが無いときは、エラーが出ないまま既定に落ちるからです。この場合Claude Codeは立ち上がっても、API通信が遮断されて何もできない状態になります。

READMEによると、~/.srt-settings.jsonが存在しても空だったり、読めなかったり、検証に失敗したりすると、srtはエラーを出して終了します。既定値に戻ることはありません。既定値は「弱い設定」ではなく「別の設定」で、戻すとファイルに書いたdenyReadや認証情報のルールまで落ちてしまうためです。

設定の適用を確実にしたいなら、--settingsで明示するのが安全です。読み込みに失敗すれば起動しないので、静かに既定へ落ちる事故を避けられます。起動後は、許可していないドメインへのcurlが拒否されることを、Claude Codeに実行させて確かめる手もあります。

何も設定しなくても遮断される書き込み先

runtimeは、リスクの高い書き込みを設定なしでも止めます。プロジェクトのルートでは、次の場所が対象です。

  • .git/hooks
  • .git/config(filesystem.allowGitConfig: trueを設定すると許可)
  • .mcp.json
  • .claude/commandsと.claude/agents
  • シェルの起動ファイル

READMEの一覧には、.bashrc、.zshrc、.gitconfig、.vscode/、.idea/なども入っています。allowWrite: ["."]と書いていても、これらへの書き込みは失敗します。denyWriteがallowWriteに優先するためです。

ただし、公式は「許可した書き込みパスには、Claude Codeが設定を読み込むほかの場所も含まれる」と警告しています。セッションがそこへ書けると、次にClaude Codeを起動したとき、サンドボックス外で動くフック、権限ルール、MCPサーバーを仕込めます。こうしたパスは、denyWriteで自分で塞ぐ必要があります。公式は具体的なパスを列挙していないので、~/.claudeを許可している場合は、その配下の設定ファイルをdenyWriteへ入れるかを検討します(例として~/.claude/settings.jsonですが、Claude Code側の書き込みが必要な機能と衝突しないか、実際に確かめてください)。

Linuxではあとからできるネストしたリポジトリをruntimeは守れない

macOSとLinuxで、遮断の効き方が違います。

項目macOSLinux・WSL2
禁止パスの判定macOS書き込みの瞬間に検査Linux・WSL2起動時に一度だけ組み立て
起動後に作られたネストしたファイルやリポジトリmacOS対象になるLinux・WSL2対象にならない

Linux・WSL2では、起動時に禁止リストを作ります。プロジェクトのルートは確実に守り、起動時点で存在するネストしたコピーは浅く探して、ベストエフォートで守ります。セッション中に作られたものは対象外です。git init、git clone、雛形生成が典型で、これらで作った.git/hooksは保護されません。

「浅く探す」深さはmandatoryDenySearchDepthで調整できます。READMEによる仕様は次のとおりです。

  • 既定値は3で、指定できる範囲は1から10
  • 大きくすると保護は強まるが、起動が遅くなる
  • プロジェクトのルート直下(深さ0)は、この値によらず常に保護される
{
  "mandatoryDenySearchDepth": 5,
  "filesystem": {
    "allowWrite": [".", "~/.claude", "~/.claude.json", "/tmp"]
  }
}

この値を上げても、起動後に作られたリポジトリは守れません。上げて効くのは、起動時にすでにある深めのネストだけです。なお、READMEには「存在しない禁止パスもLinuxでは/dev/nullのマウントなどで塞ぐ」という記述もあります。それでも公式のClaude Code側の説明は、セッション中に作られるものを対象外としています。

無人運転のあとに見直すもの

公式は、無人運転のあとに「書き込み可能にしたパス」を見直すよう求めています。Linux・WSL2ではさらに、セッションが作ったものも見直しの対象です。ネストしたリポジトリの.git/hooksや.git/configが、その典型です。

次の点は、隔離の限界として押さえておきます。

  • プロセスはホストのカーネルを共有するため、カーネルの脆弱性による脱出は理論上ありえる。カーネル水準の分離が要るなら、gVisorや別のVMを選ぶ
  • プロキシはクライアントが名乗るホスト名でドメインを判定し、暗号化された通信の中身は検査しない。ドメインフロンティングのような手法で、許可リスト外へ出られる可能性がある
  • ネットワークを許可したままでは、エージェントが読めるデータは外へ出せる。プロジェクトを書き込み可能にしていれば、そのコードも書き換えられる

境界を強くしたいなら、Dev containerや専用のVMのほうが向きます。信頼できないリポジトリを扱うなら、公式は専用のVMかクラウドセッションを勧めています。sandbox-runtimeは「Dockerなしで、MCPサーバーとフックまで含めて包みたい」ときの選択肢です。

この記事を共有:XはてブLinkedIn