本文へスキップ
メニュー
自分に必要?エージェントが手元のマシンで触れられるもの仕組みエージェントとシステムの間にある層比較組み込みサンドボックス、Docker、VM設定タスクに必要なものだけを開けるセキュリティ脅威モデルとその限界インストール
セキュリティ

役に立つ層。限界も分かっている

ai-jailは、AIコーディングエージェントを鍵やホームディレクトリ、マシンのほかの部分から遠ざけます。プロセスサンドボックスなので、カーネルはホストと共有します。悪意のあるコードが相手なら、使い捨てのVMの代わりにはなりません。

何を止めるために作られたか

エージェントは、Webページやパッケージ、リポジトリ内のファイルにそそのかされて、まずい動きをすることがあります。そのとき手を伸ばす先が次のもので、どれも見つかりません。

エージェントとプロジェクトが格子の壁の中にあります。エージェントから6本の矢印が出て、壁に跳ね返されています。外側には、ホームと鍵、シェルの秘密情報、ネットワーク、画面とクリップボード、あなたのターミナル、ジェイルのポリシーが、暗く、格子がかかった状態で並んでいます。
デフォルトの状態です。外側にあるものはどれも、あなたが自分で開けるまで外にあります。

手が届かない

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

壁が終わるところ

ジェイルとあなたのシステムは、同じカーネルの上に立っています。そのカーネルやドライバ、サンドボックスのバックエンドにバグがあれば、壁を回り込む道になり、ai-jailには打つ手がありません。仮想マシンは自前のカーネルを持ちます。境界としてより強いのはそのためです。

左では、あなたのシステムと、エージェントを入れたai-jailの檻が、あなたのカーネルという1枚の共有の土台に載っていて、エージェントから土台を通ってシステムへ破線が伸びています。右では、使い捨てのVMが、専用の別のカーネルに載ったエージェントを囲んでいます。
サンドボックスは守る対象と同じ地面を共有し、VMは自前の地面を持ち込みます。

残るリスク

  • カーネルとドライバの脆弱性。サンドボックス内のどのプロセスも、マシンのほかの部分と同じカーネルとやり取りします。
  • ターミナルエミュレータのバグ。特に、出力フィルターを無効にする--terminal-passthroughを使う場合です。
  • サンドボックスのバックエンド自体の欠陥。Linuxではbubblewrap、Landlock、seccomp、macOSではsandbox-execです。
  • プロジェクト内の秘密情報。リポジトリ内の.envファイルは、マスクしない限り読めます。ファイルをマスクする方法を見る
  • マスクの対象は、サンドボックスの起動時に存在するパスだけです。セッション中に後から作られた秘密情報のファイルは隠されません。
  • サイドチャネルと、一部の種類のプロセス間通信。
  • macOSのsandbox-execはAppleが非推奨にしており、Linuxの隔離と同等ではありません。macOSでの違いを見る

壁に穴を開けるスイッチ

以下はすべて、有効にするまでは無効です。どれも、エージェントに実際のアクセスを与えます。設定方法は設定のページにあります

スイッチサンドボックス内のものにできるようになること
--network読めるものすべてを、どこへでも送信する。通信は無制限で、ドメイン単位のフィルターはありません。
--dockerDockerデーモンを通じて、ホストのrootとして振る舞う。
--x11ほかのX11ウィンドウのキー入力を記録し、スクリーンショットを撮る。
--systemd-usersystemdのユーザーマネージャーに、ホスト上でサービスを動かすよう依頼する。
--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の読み取り、ptracebpfの呼び出しを試み、失敗することを確認します
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人目のレビュアーがいません。

RELEASE_SECURITY.mdを読む

脆弱性を報告する

公開のissueは立てないでください。GitHubの非公開の脆弱性報告機能を使い、再現手順と影響を受けるバージョンを書いてください。修正を調整するための時間もください。

よくある質問

エージェントは脱出できますか?
デフォルトの設定は、ファイル、環境、ネットワーク、ホストのIPCという通常の経路を塞ぐように作られ、テストされています。それでも、カーネルやドライバ、ターミナル、サンドボックスのバックエンドにバグがあれば、外に出られる可能性があります。これはどのプロセスサンドボックスにもある限界で、悪意のあるコードを使い捨てのVMで扱うべき理由です。
ネットワークを有効にして動かしても安全ですか?
エージェントをそのまま動かすよりは安全です。鍵もホームディレクトリもそこにはなく、送りようがないからです。ただし、エージェントは読めるものを何でも送れますし、ai-jailにドメイン単位のフィルターはありません。先にプロジェクト内の秘密情報をマスクしてください。マスクする方法を見る
監査は受けていますか?
1.0の前に内部で監査し、報告書をリポジトリで公開しています。第三者による監査は受けていません。コードはGPL 3.0で公開されており、脆弱性の非公開での報告を歓迎します。

エージェントを檻の中に

ai-jailは単一のバイナリで、デーモンもroot権限も要りません。いつものコマンドの前に1語足すだけです。

terminal
brew tap akitaonrails/tap && brew install ai-jailai-jail claude