セキュリティ
役に立つ層。限界も分かっている
ai-jailは、AIコーディングエージェントを鍵やホームディレクトリ、マシンのほかの部分から遠ざけます。プロセスサンドボックスなので、カーネルはホストと共有します。悪意のあるコードが相手なら、使い捨てのVMの代わりにはなりません。
何を止めるために作られたか
エージェントは、Webページやパッケージ、リポジトリ内のファイルにそそのかされて、まずい動きをすることがあります。そのとき手を伸ばす先が次のもので、どれも見つかりません。

手が届かない
- ホームディレクトリと、その中の認証情報。エージェントには新しい空のホームが渡されるので、
~/.sshも~/.awsも中には存在しません。 - シェルにある秘密情報。環境変数は小さな許可リストに絞られるので、exportしたトークンは外に残ります。
- ネットワーク。無効なので、エージェントが読んだものはどこにも送れません。
- ホストの共有メモリ、ディスプレイサーバー、クリップボード。エージェントの出力はフィルターを通り、クリップボード操作やターミナルへの問い合わせのシーケンスはそこで落とされます。
- ターミナルへの入力。Linuxでは、キー入力を偽装する
TIOCSTIの呼び出しをブロックします。macOSでは、ターミナルの制御を、ai-jailがその実行用に作ったターミナル1つに限定します。 - ジェイル自身のルール。リポジトリ内の
.ai-jailファイルは信頼されず、サンドボックスを厳しくはできても、緩めることはできません。
壁が終わるところ
ジェイルとあなたのシステムは、同じカーネルの上に立っています。そのカーネルやドライバ、サンドボックスのバックエンドにバグがあれば、壁を回り込む道になり、ai-jailには打つ手がありません。仮想マシンは自前のカーネルを持ちます。境界としてより強いのはそのためです。

残るリスク
- カーネルとドライバの脆弱性。サンドボックス内のどのプロセスも、マシンのほかの部分と同じカーネルとやり取りします。
- ターミナルエミュレータのバグ。特に、出力フィルターを無効にする
--terminal-passthroughを使う場合です。 - サンドボックスのバックエンド自体の欠陥。Linuxではbubblewrap、Landlock、seccomp、macOSでは
sandbox-execです。 - プロジェクト内の秘密情報。リポジトリ内の
.envファイルは、マスクしない限り読めます。ファイルをマスクする方法を見る。 - マスクの対象は、サンドボックスの起動時に存在するパスだけです。セッション中に後から作られた秘密情報のファイルは隠されません。
- サイドチャネルと、一部の種類のプロセス間通信。
- macOSの
sandbox-execはAppleが非推奨にしており、Linuxの隔離と同等ではありません。macOSでの違いを見る。
壁に穴を開けるスイッチ
以下はすべて、有効にするまでは無効です。どれも、エージェントに実際のアクセスを与えます。設定方法は設定のページにあります。
| スイッチ | サンドボックス内のものにできるようになること |
|---|---|
--network | 読めるものすべてを、どこへでも送信する。通信は無制限で、ドメイン単位のフィルターはありません。 |
--docker | Dockerデーモンを通じて、ホストのrootとして振る舞う。 |
--x11 | ほかのX11ウィンドウのキー入力を記録し、スクリーンショットを撮る。 |
--systemd-user | systemdのユーザーマネージャーに、ホスト上でサービスを動かすよう依頼する。 |
--inherit-env | シェルの環境全体を、秘密情報も含めて読む。 |
--agent-state | エージェントの保存済みログインを使う。たとえばClaudeの~/.claudeです。 |
--audio | 有効な間、音声を録音、再生する。 |
--no-private-home | 本物のホームディレクトリを見る。これは広い例外です。必要なパス1つだけをマップするほうが安全です。 |
迷ったら、起動を拒否する
指定より弱い状態で黙って起動するサンドボックスは、エラーで止まるサンドボックスより危険です。次の場合、ai-jailは停止します。
- 設定ファイルが存在するのに、不正であるか読めない場合。
- プロジェクトの
.ai-jailがシンボリックリンクである場合。グローバルの~/.ai-jailがシンボリックリンクなら、リンク先が、あなたが所有し、ほかの誰も書き込めず、プロジェクトの外にある通常ファイルのときだけたどります。 --lockdownの指定時に、カーネル側のファイルシステムルールであるLandlockがない、部分的にしか使えない、または適用に失敗した場合。--lockdown --no-landlockも拒否されます。--allow-tcp-portを指定した場合。このインターフェースではUDPを制限できないため、フラグは互換性のために受け付けますが、起動は失敗します。BWRAP_BINが、root以外の誰かが差し替えられたかもしれないbubblewrapバイナリを指している場合。警告を出して無視し、信頼できるbubblewrapがなければ起動は失敗します。
プロジェクトの検証体制
このプロジェクトは、1人のメンテナーが公開の場で運営しています。検証しているものと、していないものは次のとおりです。
- 19
- サンドボックス脱出の統合テスト。
/usrへの書き込み、~/.sshの読み取り、ptraceやbpfの呼び出しを試み、失敗することを確認します - 720
- バージョン1.22.0のソースツリーにあるユニットテスト
- 0
- 起動時のネットワークリクエスト。更新チェックは
--update-checkによるオプトインです
リリースの作り方
- リリースタグには署名があり、CIがリポジトリに固定された鍵のフィンガープリントと照合して1つずつ検証します。
- GitHub ActionはすべてコミットSHAで固定され、使えるactionは許可リストで制限されています。
- ビルドには、固定したRustツールチェーンと
--lockedの依存を使います。 - macOSのバイナリは署名され、Appleの公証を受けています。
- 各アーカイブにはSHA-256のチェックサムが付き、公開ジョブがそれをもう一度確認します。
リリース文書がまだ足りないとしているもの
- 署名用と公開用のシークレットはまだリポジトリレベルに保存されており、リリース用のenvironmentに移す必要があります。
- すべての
v*タグに署名を強制するrulesetは、まだありません。 - immutable releasesは有効になっていません。
- crates.ioへの公開には、まだトークンを使っています。trusted publishingへの移行を予定しています。
- メンテナーが1人なので、変更やリリースを確認する2人目のレビュアーがいません。
脆弱性を報告する
公開のissueは立てないでください。GitHubの非公開の脆弱性報告機能を使い、再現手順と影響を受けるバージョンを書いてください。修正を調整するための時間もください。
よくある質問
エージェントは脱出できますか?
デフォルトの設定は、ファイル、環境、ネットワーク、ホストのIPCという通常の経路を塞ぐように作られ、テストされています。それでも、カーネルやドライバ、ターミナル、サンドボックスのバックエンドにバグがあれば、外に出られる可能性があります。これはどのプロセスサンドボックスにもある限界で、悪意のあるコードを使い捨てのVMで扱うべき理由です。
ネットワークを有効にして動かしても安全ですか?
エージェントをそのまま動かすよりは安全です。鍵もホームディレクトリもそこにはなく、送りようがないからです。ただし、エージェントは読めるものを何でも送れますし、ai-jailにドメイン単位のフィルターはありません。先にプロジェクト内の秘密情報をマスクしてください。マスクする方法を見る。
監査は受けていますか?
1.0の前に内部で監査し、報告書をリポジトリで公開しています。第三者による監査は受けていません。コードはGPL 3.0で公開されており、脆弱性の非公開での報告を歓迎します。
エージェントを檻の中に
ai-jailは単一のバイナリで、デーモンもroot権限も要りません。いつものコマンドの前に1語足すだけです。
brew tap akitaonrails/tap && brew install ai-jailai-jail claude