0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Claude Code の sandbox がわからなかったので図解してみた

0
Posted at

この記事の結論

  • sandbox は、Claude が動かすコマンドが触れるファイルと通信先を、カーネルが実行中に制限する仕組み
  • 危ないコマンドの名前で断るのではなく、危ない動作そのものを止める。だから中身が分からないコマンドでも動かせる
  • Anthropic は社内利用で承認プロンプトが 84% 減ったと報告している

sandbox とは何か

皆さんがデスクトップアプリやターミナルで開いている Claude Code は、1 つのアプリケーションのプロセスとして動いています。ファイルを読む、書き換える、Web ページを取ってくる、といった機能はこのプロセスの中に組み込まれていて、Claude Code 自身が処理します。

一方、ビルドやテストのように別のプログラムを動かす必要があるときは、Claude Code はシェルにコマンドを渡します。シェルは、ターミナルで打ったコマンドを受け取り、対応するプログラムを起動する係です。Bash はシェルの一種で、ほかに zsh(macOS の標準)や fish、Windows の PowerShell があります。この「シェルにコマンドを渡す機能」が Bash ツールです。npm test と渡せば、npm というプログラムが Claude Code とは別のプロセスとして起動します。

ここが分かれ目です。プロセスの内側の機能は Claude Code が自分で処理するので、何をするかを Claude Code が把握しています。外側で起動したプログラムは別のプロセスなので、Claude Code はその中で何が起きるかを制御できません。

sandbox は、この「別のプログラム」に対して、触れるファイルの範囲通信してよい相手の範囲を先に決めておく仕組みです。範囲の外に出ようとした動作は、その場で止められます。危ないコマンドの名前を見て断るのではなく、危ない動作そのものを止めます。

止めているのはカーネルです。カーネルは OS の中心部で、ファイルを読む、書く、インターネットにつなぐ、といった操作をすべて引き受けています。プログラムはこれらを自分ではできず、必ずカーネルに頼みます。どの言語で書かれたどんなプログラムでも同じです。

プログラムがどれだけ違っていても、ファイルや通信に触る道はカーネルの 1 本しかありません。だから sandbox はここで止めます。

sandbox が無い場合、プログラムがカーネルに「このファイルを開きたい」「この相手と通信したい」と頼めば、そのまま通ります。パソコンのどのファイルでも、インターネットのどこへでも届きます。sandbox がある場合、頼むところまでは同じですが、カーネルが先に決めた範囲と照合し、外なら止めます。コマンドが通る道を最初から最後まで描くと、次のようになります。

permission ルールは Claude Code のプロセスの中で、コマンドを動かす前に判定します。シェルから先はプロセスの外で、sandbox はその外側だけを対象にします。permission ルールは次の節で説明します。

だから、範囲をカーネルで守ると逃げ道がありません。プログラムが何をしようと、カーネルに頼まずにファイルや通信に触ることはできないからです。

実行前の関門: permission ルール

Claude Code は Manual モードでは、コマンドを動かす前に「これを動かしてよいか」と承認を求めます。Pro / Max / Team プランでは初期のモードが auto になる場合があり、その場合は人の代わりに分類器が判断しますが、この節ではまず Manual モードの流れで説明します。どのコマンドを毎回聞き、どれを聞かずに通すかを決めるのが permission ルールです。ルールが見ているのは、これから動かすコマンドの文字列だけです。文字列を見ても、そのコマンドが実際に何をするかまでは分かりません。

ここに問題があります。先ほど図 1 で登場した npm test を例に、順に見ていきます。

npm test を許可すると、何を許可したことになるのか

Claude Code が「npm test を動かしたい」と言い、あなたが承認したとします。このとき許可したのは npm test という文字列ですが、実際に何が動くかは、プロジェクトの package.json が決めます。

{
  "scripts": {
    "test": "vitest"
  }
}

scripts.test に書いたコマンドが走るだけです。テストを自動で探して実行する仕組みではありません。

npm にはもう一つ、インストール時に自動でスクリプトを走らせる preinstallpostinstall があります。依存パッケージ側にこれが書かれていると、こちらが実行を指示していないコードが、こちらの権限で動きます。

2025 年 9 月から npm で広がった Shai-Hulud というマルウェアは、この仕組みを使いました。初めて聞く方は、リンク先の Unit 42 の解説(日本語)の冒頭だけ読むと、以下の流れが追いやすくなります。

  1. 開発者が依存パッケージをインストールする
  2. postinstall が発火し、npm トークン、GitHub のアクセストークン、AWS などのクラウド鍵を盗む
  3. 盗んだ npm トークンでレジストリに本人として認証する
  4. その開発者が公開している他のパッケージに自分を注入し、新しいバージョンとして公開する
  5. それをインストールした次の開発者で 1 に戻る

攻撃者が操作しなくても広がる、自己増殖型です。Datadog Security Labs は 2025 年 11 月の変種について、796 のパッケージが乗っ取られ、合計で週 2000 万ダウンロードを超える規模だったと報告しています。Unit 42 によると、この変種は認証情報を盗めなかった場合にホームディレクトリの破壊を試みるところまで進みました。

仕組みから考えると、パッケージを公開していない人は増殖の経路にはなりません。認証情報は同じように盗まれます。

npm test という文字列からは、ここまで判断できません。

では npm test を deny すればよいかというと、テストを動かさない開発はありません。かといって「危ないときだけ止める」という判定は、文字列しか見ない permission ルールにはできません。deny するか通すかの二択で、どちらも選べない。これがここでの問題です。

承認を増やしても解決しない

では確認を増やせばよいかというと、そうもいきません。

Anthropic は sandbox を発表した記事で、承認疲れを問題に挙げています。操作のたびに承認を求められると開発が遅くなり、人が中身を読まなくなります。許可の仕組みがあるせいで、かえって安全でなくなる状態です。

事前に判定するか、実行中に閉じ込めるか

sandbox はこの前提を裏返します。

判定のタイミング 判定の材料 対象
permission ルール ツールが動く前 コマンドの文字列 すべてのツール
sandbox 動いているプロセスに対して OS が強制する境界 Bash とその子プロセス

sandbox は実行してよいかを決めません。決めるのは、実行できてしまう範囲です。

公式ドキュメントはこう説明しています。

境界を強制するのは OS です。モデルが何を実行しても、許可したコマンドが名前から想像される以上のことをしても、この線は動きません。

範囲が先に決まっていれば、1 コマンドずつ承認する必要がなくなります。実際、sandbox を有効にすると、sandbox の中で動くコマンドは承認なしで通す設定が既定になります。承認が減るのはこのためです。

ただし、permission ルールが消えるわけではありません。deny ルールに当たるコマンドは止まり、git push のように中身を指定した ask ルールは sandbox の中でも承認を求めます。sandbox の外で動くもの(ファイルの直接編集など)は、これまでどおり permission ルールが決めます。

守るのは 2 軸。片方だけでは穴が残る

sandbox が制限するのは 2 つだけです。ファイルとネットワークです。

ファイル側の既定値は、読みと書きで大きく違います。

既定の範囲
書き込み 作業ディレクトリと、セッション用の一時ディレクトリだけ(--add-dir で足した場所があればそれも)
読み取り パソコンのほぼ全体。~/.ssh~/.aws/credentials も読める

理由は公式には書かれていませんが、読み取りまで絞るとビルドもテストも動かなくなるからではないでしょうか。

そのぶんネットワーク側が重い役割を持ちます。sandbox の外にプロキシ(通信を中継して行き先を確かめる係)が立ち、そこを通らないと外に出られません。既定では許可する接続先がゼロで、初めての相手への接続はその場で承認を求められます(auto モードでは、人の代わりに分類器がその接続を審査します)。

認証情報が守られる理屈は少し変わっていて、読ませないのではなく行き先を塞ぎます。

情報の流出は「読む」と「外に出す」の 2 工程です。ファイル側の隔離は (1) を止めません。ネットワーク側の隔離が (2) を止めます。

逆に、ネットワークだけ塞いでファイルの書き込みが自由だと抜け道ができます。ターミナルが起動時に読み込む設定ファイルに 1 行書き足せば、次にターミナルを開いた瞬間、sandbox の外で、利用者自身の手で実行されるからです。sandbox の中のプロセスは自力で外に出られませんが、外で動く未来の実行に相乗りはできます。

Anthropic も公式記事で、両方が必要だと述べています。片方を緩めるときは、もう片方の制限を打ち消していないか確認してください。

Shai-Hulud が sandbox の中で発火したら

答えは、npm test を deny せず、sandbox の中で動かすことです。ここまでの話を、先ほどの攻撃の流れに当てはめます。

攻撃の段階 sandbox の中では
preinstallpostinstall が発火する 止めません。sandbox はコマンドの可否を決めないからです
認証情報を読む 既定では読めてしまいます。読ませないには、守るファイルを設定で指定します
盗んだものを外に送る 許可した相手以外には送れません。既定では許可する相手がゼロで、初めての相手への接続はその場で承認を求められます(設定で、問い合わせ無しに遮断することもできます)
他のパッケージに自分を注入して公開する 公開先を許可していて、公開用のトークンが読める状態なら通ります。トークンを読ませない設定が要ります
ホームディレクトリを破壊する 書けるのは作業フォルダだけなので、外には手が出せません

npm test という文字列を見て判断する代わりに、何が起きても被害が箱の外に出ない状態を先に作っておく。これが sandbox の答えです。どのファイルを守り、どの相手を許可するかは、設定で決めます。

sandbox があると、承認を機械に任せられる

Claude Code には auto モードがあり、人の代わりに分類器と呼ばれる別のモデルが行為を審査します。分類器は判断を間違えることがあります。sandbox は、分類器が何を通そうと範囲の外には出さない、別の層です。

公式ドキュメントは auto モードについて「隔離は不要だが、sandbox やコンテナが多層防御になる」と説明しています。承認を減らしても安全と言える根拠は、判断の精度ではなく、この境界にあります。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?