サンドボックスは、Claude Codeにやらせる作業をパソコンの一部だけ触れる状態に閉じ込める仕組みです。有効にしたとき、私は「これで危ないことは起きない」と思いました。誤解でした。

公式ドキュメントにこう書かれています。既定の読み取りはコンピューター全体に許可されていて、一部の拒否されたフォルダを除く。そして注意書きとして、この既定では ~/.aws/credentials~/.ssh/ のような認証情報ファイルも読めると明記されています。

制限しているのは書き込みと通信

境界は、Claude Codeが自分でパソコンに打ち込む命令(と、そこから連鎖して動くもの)に対して、ファイルと通信の2方向にかかります。

ファイル側。 既定で書き込めるのは、いまの作業フォルダとその下と一時フォルダだけ。設定ファイルや /bin/ の中身は変えられません。ここは強い。

通信側。 既定で許可されている接続先はゼロで、必要になるたびに確認が入ります。

つまり書き込みと通信は絞られているが、読み取りは絞られていない。書き換えられないだけで、見られはします。ここが要点です。

有効にするには /sandbox を打ちます。macOSは準備が不要で、LinuxとWSL2では bubblewrapsocat という2つの部品を別に入れます。

Windowsをそのまま使っている場合は対応していません。 WSL2(Windowsの中でLinuxを動かすWindows標準の仕組み)の中で動かす形になります。

認証情報を塞ぐ設定

読み取りを絞る専用の設定があります。sandbox.credentials で、ファイルと環境変数(パスワードのようなものをパソコンに覚えさせておく箱)を指定して守ります。

書く場所は ~/.claude/settings.json です。無ければ作ります。JSONという形式で、カッコと引用符の並びをそのまま真似れば動きます。

{
  "sandbox": {
    "enabled": true,
    "credentials": {
      "files": [
        { "path": "~/.aws/credentials", "mode": "deny" },
        { "path": "~/.ssh", "mode": "deny" }
      ],
      "envVars": [
        { "name": "GITHUB_TOKEN", "mode": "deny" }
      ]
    }
  }
}

書き換えるのは pathname の中身だけです。

大事な点を書いておきます。組み込みの拒否リストはありません。 自分が書いたものだけが守られます。書かなければ何も守られない。

AWSの鍵やSSHと書くとエンジニアの持ち物に見えますが、社内システムにつなぐパスワードを書いたファイルや外部サービスの連携キーを置いている人は同じ話です。

既定を逆にしてほしい部分ですが、塞ぐと動かなくなるツールが多いのだろうとは想像がつきます。

消さずに隠す選択肢もある

deny は環境変数を消します。消すと、その変数で認証しているツールが動かなくなります。

そこで mask があります。サンドボックスの中にはダミーの値を見せ、通信が外へ出るときに本物へ差し替える仕組みです。コマンドもそのログも本物を持たないまま、認証だけは通る。

差し替えを行うのはプロキシ(Claude Codeが通信の出入り口に置く中継役。自分で用意するものではありません)です。ただし通信はTLSで暗号化されていて中継役にも中身が読めないので、読める状態にする network.tlsTerminate の設定が要ります。設定しないとダミーがそのまま送られて認証が失敗します。失敗する方向に倒れるので、気づかず漏れることはありません。

2026年8月4日のv2.1.221で、ファイルに対しても mask が使えるようになりました。ただしLinuxとWSLだけで、macOSでは deny と同じ扱いになります。 自分のバージョンは claude --version で確認できます。

なお同日時点で、解説ページには「ファイルは deny のみ」と書かれたままでした。changelogが先で、ドキュメントが追いついていない状態です。

設定の置き場所で効き方が変わる

ユーザー設定  ~/.claude/settings.json   自分だけの設定
管理設定      会社が配る設定            管理者が決める
プロジェクト  .claude/settings.json    作業フォルダに同梱される

mask は本物の認証情報を指定先へ送る許可を与える設定なので、いちばん下のプロジェクト側からは効きません。他人が用意したフォルダを開いただけで鍵の送信先を書き換えられたら困るからです。

通信を確認なしで拒否する

v2.1.219で sandbox.network.strictAllowlist が入りました。許可リストに無い接続先を、確認を出さずに拒否する設定です。既定は確認が出る形なので、うっかり許可してしまう余地があります。放置して長時間走らせるときは立てておくほうが安全です。

これも mask と同じで、プロジェクト側の設定からは効きません。ユーザー設定、管理設定、--settings のみです。

権限の考え方そのものは別記事で扱いました。

壁として頼りきれないと公式が書いている

中継役は接続先の名前を見て許可を判断し、さきほどの設定をしない限り中身は見ません。そのため許可リストの外へ到達する手口があり得ると公式が書いています。とくに github.com のような広い指定は、データを外へ出す経路になり得る。

私はこれを読んで、api.github.com のように必要な範囲まで絞る形に変えました。手間は増えましたが、広く許可して安心するより気分がいい。

権限チェック自体の抜け穴も実際に見つかって直っています。v2.1.221では、隠したコマンドが権限チェックを通り抜ける問題などが修正されました。設定を書けば絶対に安全、という種類のものではありません。

確認を全部飛ばす選択肢との関係は、こちらにまとめています。

私が最初に書いた2行

全部を設定するのは大変なので、最初にやる価値が高い2つだけ挙げます。

~/.ssh と、使っているクラウドの認証情報フォルダを credentials.filesdeny で入れる。これだけで読まれたら困るものの大半は塞がります。

そのうえで strictAllowlist を立てる。面倒な方向から始めて緩めるほうが、緩い状態から絞るより漏れが少ないというのが、やってみての感想です。