本文へスキップ
AI活用

Claude Codeサンドボックス設定ガイド|有効化だけでは残る3つの穴

Hirokuma
9分で読める
Claude Codeサンドボックス設定ガイド|有効化だけでは残る3つの穴

sandbox.enabled: true を書いた時点では、壁はまだ完成していません。既定のままだと、資格情報は3つの経路で壁の内側から読めるか、外へ出ていけます。 ファイル読取、環境変数の継承、ネットワークの許可リスト。この3つを設定で閉じて、はじめてサンドボックスは「壁」として機能し始めます。

この記事は、Claude CodeのBashサンドボックスを有効化した人、これから有効化する人に向けて、有効化の次にやる設定を整理します。前回の入門記事では「権限ルールは検問、サンドボックスは壁」という層の分け方と、Bashサンドボックス・Dev Container・クラウド実行の3段の使い分けを書きました。今回はその1段目、Bashサンドボックスの設定の中身です。

Claude Codeのサンドボックス入門|3段の隔離と権限ルールの限界Claude Codeの実行環境を隔離する3つの方法(Bashサンドボックス・Dev Container・クラウド実行)を整理します。symlinkやteeで権限ルールが漏れた修正履歴から「ルールと壁は別物」と考える理由、3段の使い分けの判断軸、壁の内側に持ち込むものの棚卸しまでまとめます。www.tentspace.net

「有効化しただけ」の状態を疑う

私はSNS運用のRoutineをClaude Codeの無人実行で回していて、日次の定常処理はクラウドの使い捨て環境に寄せています。手元のマシンで対話的に使う作業にはBashサンドボックスという構成です。ただ、enabled: true を書いた後の設定まで詰めているケースは、周りを見ても多くないはずです。壁を立てた安心感で、壁の中身は見ないままになりやすい。

その状態を具体的に指摘しているのが、クラスメソッドの検証記事です。sandbox.enabled: true だけでは、侵害されたnpmパッケージのような供給連鎖攻撃経由の資格情報窃取に対して不十分で、既定のままでは3つの穴が残る、という整理です。

クラスメソッド: Claude Code Bashサンドボックスのセキュア設定結構フクザツです!dev.classmethod.jp

なお、この記事で挙げる既定値と設定キー名は上記出典の記述に基づきます。私の環境での全項目の再現検証はまだです。設定を入れる前に、手元のバージョンの公式ドキュメントで確認してください。

穴1: ファイル読取——拒否リスト以外は読める

1つ目はファイル読取です。出典の整理では、サンドボックス内のプロセスは、拒否ディレクトリを除いたファイルシステム全体を既定で読めます。つまり ~/.aws/credentials や ~/.ssh/ も、拒否リストに入れない限り読める側です。

サンドボックスと聞くと「作業ディレクトリの外は見えない」を想像しがちですが、既定の向きは逆で、読み取りは原則許可、拒否だけ列挙。書き込みの制限とは別物です。侵害されたパッケージのインストールスクリプトが動いたとき、最初に探しに行くのはまさにこの手のパスなので、ここが素通しだと壁の意味が薄くなります。

対応する設定は2系統あります。資格情報ファイルを対象にした sandbox.credentials.files、読ませたくないディレクトリを列挙する sandbox.filesystem.denyRead。趣旨はどちらも同じで、「この環境で読める必要がないものを申告して外す」です。

穴2: 環境変数——親の変数をそのまま継承する

2つ目は環境変数です。サンドボックス内のプロセスは、親プロセスの環境変数を既定でそのまま継承します。シェルに NPM_TOKEN やAWSの資格情報を環境変数で置いている人は、その値がサンドボックスの内側からも見えます。

これはファイル読取より見落としやすい穴です。ファイルは「どこに置いたか」を覚えていますが、環境変数は .zshrc や direnv が黙って積んでいくので、いま何が載っているかを正確に言える人は少ない。env | grep -iE 'token|key|secret' を一度流してみると、思ったより多くの値が出てきます。

対応する設定は sandbox.credentials.envVars で、渡さない変数を指定します。私の運用では、SNS公開系のトークンをそもそもローカルに置かず、サーバー側(Cloudflare WorkersのKV)だけに置く形にしています。渡さない設定より、最初から手元に無い方が申告漏れも起きません。この置き場所の設計は認証ガイドの記事に書いた通りです。

MCPサーバーの認証ガイド|トークンの置き場所と漏れる場所の設計MCPサーバーの認証と資格情報の扱いを、実運用中の自作サーバーの実装で解説します。Bearer検証の実装判断、トークンをWorker KVだけに置く境界、クライアント側のエラー文へ資格情報が出ていた漏れ口まで、置き場所と出さない場所の設計を整理します。www.tentspace.net

穴3: ネットワーク——許可リストは運用の中で膨らむ

3つ目はネットワークのegress、外向きの通信です。許可リストは空から始まるので、初期状態は絞られています。問題は運用の中で起きます。コマンドが未知のドメインへ接続しようとするたびに確認が出て、そこで「今後は聞かない」を選び続けると、許可リストは静かに膨らんでいく。数週間後には、どのドメインをなぜ許可したのか誰も説明できないリストができあがります。持ち出し経路として一度開いたドメインは、次からは確認なしで通る側です。

出典が挙げる対応は sandbox.network.strictAllowlist: true と sandbox.network.tlsTerminate です。前者で許可リストを厳格化し、後者でTLSを終端して通信の中身を検査可能にします。

公式側も、許可の単位を細かくする方向に動いています。2.1.271(2026-09-14)で、auto modeのサンドボックス実行にコマンド単位のallowed_domainsが入りました。そのコマンドが必要とするホストだけがコマンドと一緒に審査されて開き、他のホストは拒否される。セッション全体に1枚の許可リストを掛けるより狭い単位です。

Claude Code公式チェンジログRelease notes for Claude Code, including new features, improvements, and bug fixes by version.code.claude.com

ひとつ未検証の論点を正直に書いておくと、コマンド単位の許可は、同じホストを何度も叩く定常処理では審査回数が増える側に効く可能性があります。無人Routineに入れるなら、先に発火回数を数えてからだと考えています。

設定の本体は、壁の厚さではなく持ち込みの申告

3つの穴と設定キーを並べて気づいたことがあります。credentials.files も credentials.envVars も denyRead も、壁を厚くする設定ではありません。壁の内側に何を置いているかを申告する設定です。

前回の入門記事の最後に、壁は外側しか守らないので、内側に持ち込む認証情報・コード・依存を先に棚卸しする、と書きました。あのときは運用の心構えとして書いたのですが、今回の設定群はその棚卸しを設定言語でやらせるものだと読めます。つまりBashサンドボックスの設定が複雑なのは、壁の仕様が複雑だからではなく、私たちが壁の内側に置いているものが多いからです。出典の著者も「相当に複雑」で、安全性と開発体験のトレードオフは避けられないと書いています。この複雑さはツールの欠点というより、手元の環境に積んできた資格情報の在庫リストがそのまま出ているのだと思います。

この見方に立つと、周辺の動きも同じ線に乗ります。GitHubも2026-09-23にCopilotアプリへローカルサンドボックスを追加して、エージェントの実行隔離をクライアント側で持つ方向に入りました。隔離の仕組み自体は各社の標準装備になりつつあります。そうなると差が出るのは「隔離しているか」ではなく「既定で何が漏れるか」を各自が把握しているか——これは私の推測ですが、少なくともClaude Codeの3つの穴は、その把握を先にやった分だけ差になります。

GitHub Changelog: Local sandboxing in the GitHub Copilot appLocal sandboxing helps reduce the potential impact of unintended commands by limiting access to files, network resources, and credentials on your machine. In the GitHub Copilot app, you configure it per project for local repository and working tree sessions.github.blog

設定する順番——読める・見える・出ていけるを閉じる

まとめとして、有効化の次にやることを順番にします。

  1. 現状を数える。~/.aws や ~/.ssh など、この環境から読める資格情報ファイルを列挙する。env で環境変数に載っている秘密を数える
  2. 読ませない。sandbox.credentials.files と sandbox.filesystem.denyRead で、作業に不要な資格情報ファイルを申告して外す
  3. 見せない。sandbox.credentials.envVars で秘密の環境変数を渡さない。可能なら、そもそもローカルの環境変数に秘密を置かない形へ寄せる
  4. 出て行かせない。sandbox.network.strictAllowlist: true で許可リストを厳格化し、「今後は聞かない」で膨らませない。膨らんだリストは定期的に説明できるかで棚卸しする

順番に意味があります。1で在庫を数えないまま2〜4を書くと、申告漏れに気づけません。設定は壁の仕様書ではなく持ち込み品の申告書なので、申告の前にまず在庫調べです。

enabled: true で止まっている人は、まず手元で env | grep -iE 'token|key|secret' と ls ~/.aws ~/.ssh を流すところから始めてみてください。出てきた行数が、いまの壁の内側に置いてあるものの数です。