起動時に起きること
毎回、一瞬で終わります。その後バックグラウンドに残るものはありません。

ルールを読む
ai-jailは、あなた自身の~/.ai-jailファイルを信頼します。プロジェクト内の.ai-jailファイルは信頼できないものとして扱い、サンドボックスを厳しくはできても、緩めることはできません。コマンドラインのフラグはどちらよりも優先されます。
サンドボックスを組み立てる
ai-jailは、エージェントが存在する前に、下で説明する各層を用意します。設定ファイルが読めなかったり不正だったりした場合は、弱いルールで起動せずに停止します。
中でエージェントを起動する
エージェントも、それが起動するスクリプトやパッケージ、MCPサーバーも、同じ壁を引き継ぎます。エージェントが終了すると、ai-jailも終了します。
外側から内側へ、層を順に見る
ai-jailは、1枚の壁だけで持ちこたえられるとは考えていません。Linuxでは、エージェントはカーネルが強制する5枚の壁の内側にいます。さらに、入るものと出るものに1つずつフィルターがかかります。

名前空間
bubblewrap- これは何か
- 名前空間は、カーネルがプロセスに与える、そのプロセス専用のシステムの見え方です。ai-jailはその作成をbubblewrapに任せます。Flatpakがデスクトップアプリのサンドボックス化に使っているのと同じ小さなツールで、rootは要りません。
- 何を止めるか
- エージェントには専用のプロセス一覧と専用のホスト名(
ai-sandbox)が与えられます。ホスト上のプログラムとのプロセス間通信の経路はなく、--networkを渡さない限りネットワークもありません。ai-jailが落ちれば、中のものもすべて一緒に落ちます。
ファイルシステム
マウント- これは何か
- 名前空間の中には、ai-jailがマウントしたものしか存在しません。プロジェクトは実際のパスのまま読み書き可能、
/usrなどのシステムディレクトリは読み取り専用です。ホームディレクトリと/tmpは新しく作られ、メモリ上に置かれます。 - 何を止めるか
~/.ssh、~/.aws、~/.gnupg、~/.docker、ブラウザのプロファイルは組み込みのリストに載っており、決してマウントされません。プロジェクトの外に書いたものは、セッションが終わると消えます。
Landlock
kernel 5.13+- これは何か
- LandlockはLinuxカーネルの機能で、プロセスがファイルへのアクセス権を自分から恒久的に手放せるようにします。ai-jailはこれを使い、ファイルシステムのルールをカーネル内の2つ目の許可リストとしてもう一度適用します。
- 何を止めるか
- マウントの層にミスや抜け道があっても、それだけではリスト外のパスに届きません。読み取り専用は読み取り専用のままです。Landlockに対応していない古いカーネルでは、ai-jailはその旨を表示し、残りの層で続行します。
seccomp
システムコール- これは何か
- プログラムはシステムコールを通じてカーネルに処理を依頼します。seccompはその呼び出しにかけるフィルターです。ai-jailはこれを使い、コーディングエージェントにはまず必要のないシステムコールを拒否します。
- 何を止めるか
- フィルターが止めるのは、
ptrace、mount、bpf、カーネルモジュール、io_uring、カーネルキーリング、rawソケット、そしてターミナルにキー入力を送り込むTIOCSTIです。コンパイラやランタイムが動き続けるよう、あえてブロックリスト方式にしています。
リソース制限
rlimits- これは何か
- プロセスツリーが使える量にカーネルがかける上限です。プロセスは4,096個、開けるファイルは65,536個までで、コアダンプは無効です。ロックダウンモードでは1,024と4,096に下がります。
- 何を止めるか
- fork爆弾や暴走したスクリプトは、マシンを固まらせる前に、ジェイル内の上限に当たって止まります。エージェントが上限を引き上げ直すことはできません。
環境変数の許可リスト
入るもの- これは何か
- シェルには変数がたくさんあり、その中にはAPIキーも混ざっています。ai-jailは環境を空にして、短いリストだけを渡します。
PATH、HOME、TERM、ロケール、プロキシと証明書の設定です。 - 何を止めるか
- シェルにexportしてあるトークンやクラウドの認証情報は、エージェントに届きません。タスクに必要なときは、
--envで名前を指定して1つずつ渡します。
ターミナルプロキシ
出るもの- これは何か
- エージェントは専用の擬似ターミナルの向こうで動き、その出力は画面に届く前にターミナルのパーサーを通ります。最下行にai-jailのステータスバーを描くのもこのプロキシです。
- 何を止めるか
- プロキシは、クリップボードに触れたりターミナルに問い合わせたりするエスケープシーケンスを取り除きます。tmuxやzellijの中では、入れ子のターミナル同士がリサイズで衝突するため、プロキシは自動で無効になります。
macOSでは壁が薄くなる
macOSには名前空間もLandlockもseccompもありません。ai-jailは同じポリシーを、Apple純正のサンドボックスであるsandbox-execのプロファイルに変換します。これがLinuxの隔離と同等ではないことは、ai-jailのドキュメントにもはっきり書いてあります。

| Linux | macOS | |
|---|---|---|
| バックエンド | bubblewrap、続いてLandlock、seccomp、リソース制限 | 起動のたびに生成したプロファイルを使うsandbox-exec。Appleはこれを非推奨にしていますが、カーネル拡張なしで使えるもっと良い手段はありません。 |
| ホームディレクトリ | メモリ上の新しいホーム。本物のホームはマウントされません。 | プロファイルは全体の読み取りを禁止した状態から始め、エージェントに必要なパスだけを許可します。本物のホームは閉じたままです。 |
/tmp | 専用で、終了時に破棄 | マウント名前空間がないため、ホストの/tmpです。TMPDIRは起動ごとに作る専用フォルダを指し、許可される一時パスはそこだけです。 |
| コピーオンライトのマップ | --overlay-mapを使うと、エージェントはコピーに書き込みます | 読み取り専用のマップとして扱われます |
| ネットワーク | デフォルトで無効。専用のネットワーク名前空間に入ります | デフォルトで無効。ロックダウンでは、--networkを付けても常にブロックされます。 |
| ほかのプログラム | 見えません。プロセス一覧は専用で、ホストのIPCもありません | --macos-host-ipcを渡さない限り、Mach、IOKit、ホストのIPCは拒否されます |
なぜこの部品を選んだか
ai-jailは、自前で書くセキュリティ関連のコードをできるだけ少なくしています。土台はbubblewrapです。小さく、主要なディストリビューションすべてでパッケージになっていて、Flatpakを通じて毎日使われています。その上にカーネルの機能を重ねます。
| 選択肢 | 採用しなかった理由 |
|---|---|
| Firejail | 用は足せますが、setuid rootのバイナリであり、その設計に起因するCVEがいくつも出ています。bubblewrapはrootなしで動きます。 |
| bubblewrapをRustで書き直す | 上流で修正が入り続ける約50 KBの依存を1つ避けるために、セキュリティ上重要な500行超のコードを自分たちだけで保守し、パッチを当て続けることになります。 |
| nsjail | 機能は十分ですが、サーバー向けの作りで、設定はprotobuf形式のファイルです。パッケージとして入手できる環境も限られます。 |
| systemd-nspawn | systemdが必須なので、コンテナの中やsystemdのないシステムでは動きません。 |
読み切れる小ささ
ツール全体が1本の同期的なRustプログラムです。asyncランタイムもデーモンもコンテナイメージもありません。
- 1
- インストールするバイナリ
- 8
- 直接の依存
- 720
- ソース内のユニットテスト
- 19
- 実際のサンドボックスからの脱出を試みるテスト
ai-jailリポジトリのバージョン1.22.0で数えた値です。
エージェントを檻の中に
ai-jailは単一のバイナリで、デーモンもroot権限も要りません。いつものコマンドの前に1語足すだけです。
brew tap akitaonrails/tap && brew install ai-jailai-jail claude