エージェントに npm install を走らせた時点で、そのプロセスからは ~/.ssh/id_ed25519 も ~/.aws/credentials も読めます。危ないことはしないでとプロンプトに書いても、コマンドを覗いて弾くラッパーを挟んでも、止めているのは文字列であって操作ではありません。
文字列を見ている限り、抜けられます
cat ~/.ssh/id_ed25519 を禁止語として弾いたとします。f=~/.ssh/id_ed25519; cat $f は別の文字列です。bash -c で包んでも、tar に食わせても同じで、パターンは足すたびに増えていきます。
シンボリックリンク(別の場所を指す見かけ上のファイル)も厄介です。/work の下だけ許可したつもりでも、ln -s ~/.aws /work/x を作られると、許可したパスの下から外が読めてしまいます。リンクを解決してから判定すればよさそうに見えますが、判定した直後に張り替えられると通ってしまいます。この種の競合は古くから知られていて、ユーザー空間だけで完全に塞ぐのは困難です。
ファイルを開く操作そのものは、必ずカーネル(OSの中核)を通ります。そこで拒否されれば、文字列をどう組み立てても結果は変わりません。
macOS の Seatbelt
macOSにはプロセスが自分自身に制限をかける仕組みがあり、S式に似たプロファイルで記述します。既定を拒否にしてから、必要なものだけを開けていきます。
(version 1)
(deny default)
(allow file-read* (subpath "/work"))
(allow file-write* (subpath "/work"))
(allow process-exec)
sandbox-exec コマンドから試せます。ChromeやSafariの描画プロセスも同じ系統の仕組みの上で動いており、ブラウザが見知らぬコードを開いても平気でいられるのは、最後の砦がここにあるためです。
Linux の Landlock と seccomp
Linuxでは役割が二つに分かれています。
Landlockは5.13で入ったLSM(Linuxにセキュリティ機能を足す仕組み)で、管理者権限がなくてもプロセスが自分のファイルアクセスを縛れます。許すパスを宣言し、それ以外を閉じます。後のバージョンではTCPの接続や待ち受けも扱えるようになりました。使えるABI(提供される機能の版)はカーネル次第のため、実装する側は起動時に問い合わせて、足りない機能をどう扱うかを決める必要があります。
seccomp(システムコールを絞るLinuxの仕組み)は、プログラムがOSへ出す要求そのものを制限します。BPFのフィルタで番号と引数を見て、通す・エラーを返す・プロセスごと終了させる、を選びます。ファイルの範囲はLandlock、そもそも呼ばせたくない操作はseccompという住み分けです。
どちらも一度かけたら外せません。特権も常駐デーモンも要りません。
表現できないとき、どちらに倒すか
要求された制限をカーネルが表現できない場面は必ず来ます。Landlockのない古いカーネル、ネットワーク制限に対応していないABI、といった具合です。
ここで緩めて実行すると、利用者は制限がかかっていると思い込んだまま、かかっていない状態で使うことになります。何もしていないより危険な状態です。断る側へ倒す設計を fail-closed と呼びます。実行できないと利用者に伝えるほうが、静かに素通しするより安全です。
止まったことを、どう見せるか
サンドボックスの主張は、破ろうとして破れなかった記録でしか裏づけられません。脱出を試みるコードを一覧にして公開し、何件中何件が止まったかを示します。止められなかった行も、消さずに残します。
Aid-Onが公開しているportaでは、公開中の脱出コーパス(脱出を試みるコードの集まり)に対して、macOSで17件中17件、Linuxで20件中20件が止まっています。数字そのものより、何を試したうえでの数字なのかが読めることに意味があります。試していない攻撃は、当然止まりません。
コンテナで足りるなら、それで構いません
同じことはコンテナでも実現できます。ただしイメージを用意し、デーモンを動かし、その中に環境を作り直す必要があります。「このディレクトリとこのホストだけに閉じて、手元のclaudeを一回走らせたい」という用途には、手順が多すぎます。
カーネルの機能を直接使えば、普段の環境のまま権限だけを狭められます。エージェントは自分が閉じ込められていることに気づかないまま、いつもどおり動きます。
渡さなかったものを、止める層
WASIが「何を渡すか」を決める層だとすれば、ここは「渡していないものが本当に使えない」ことを引き受ける層にあたります。宣言と執行は別のもので、片方だけでは境界になりません。
自社でエージェントを動かす仕組みを検討する際は、二点をご確認ください。制限を執行しているのは誰か(プロンプトか、ラッパーか、カーネルか)。そして、表現できない制限を求められたときに、緩めて動かす作りなのか、実行を断る作りなのか。この二つで、その仕組みがどこまで頼れるかが判断できます。