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

デフォルトは閉。スイッチはあなたの手に。

オプションなしでは、エージェントに渡るのはプロジェクトだけです。ネットワークもログイン情報も鍵もありません。タスクに必要なものをスイッチ1つずつ開けていき、逆にジェイルをさらに閉じることもできます。

設定の出どころは3つ

設定は、プロジェクト内のファイル、ホームディレクトリのファイル、あなたが打つフラグから来ます。権限の弱いものから順に並べています。

3つの設定元がジェイルにつながっています。プロジェクトの.ai-jailファイルはジェイルを厳しくすることしかできません。グローバルの~/.ai-jailファイルは信頼されます。コマンドラインのフラグはどちらよりも優先されます。ジェイルの中では、エージェントがスイッチの列の奥にいて、スイッチのほとんどはオフです。
cloneしたリポジトリが、自分のジェイルを開けることはできません。

プロジェクトの.ai-jail

ai-jailはこれを信頼できないものとして扱います。ジェイルを厳しくはできても、開けることはできません。ai-jailがシンボリックリンク越しにこのファイルを読むことはなく、エージェントにはその場所に空のファイルが見えます。

グローバルの~/.ai-jail

あなたのものなので、ai-jailは信頼します。すべての実行に適用される基本テーブルと、コマンドの最初の単語で選ばれる[commands.<name>]テーブルを持てます。

コマンドラインのフラグ

フラグの権限が最も強くなります。ほとんどのスイッチは--network--no-networkのように対になっているので、ファイルが開けたものをフラグで閉じることもできます。

コマンドテーブルでは、単一の値は基本テーブルの値を置き換え、マップやマスクなどのリストは基本テーブルに追加されます。

~/.ai-jail
# 基本:すべてのコマンドに適用hide_dotdirs = [".my_secrets"]mask = [".env", ".env.*"] # コマンドが"claude"で始まるときだけ[commands.claude]network = trueagent_state = trueenv_pass = ["ANTHROPIC_BASE_URL"]mask = ["*.pem"]

スイッチ一覧

どの行も、指定するまでは無効です。機能を開けるフラグにはそれぞれ、閉じ直すための--no-付きの対があります。赤いバッジは、ジェイルを弱めるスイッチの印です。全一覧と理由はセキュリティのページにあります

ネットワークとサービス

フラグ設定キー動作リスク
--networknetwork = true制限なしのネットワークアクセス。エージェントは読めるものを何でも外へ送れます。ジェイルを弱める
--sshssh = true読み取り専用の~/.sshとSSHエージェントのソケット。git pushが動くようになります。1つだけ開ける
--dockerno_docker = falseDockerソケット。デーモンはホストをマウントしたコンテナを起動できるので、事実上そのマシンのroot権限です。ジェイルを弱める
--tailscaletailscale = trueTailscaleのソケット。1つだけ開ける
--systemd-usersystemd_user = truesystemdのユーザーバス。エージェントはユーザーマネージャーに、ホスト上でサービスを動かすよう依頼できます。Linuxのみ。ジェイルを弱める

エージェントと環境

フラグ設定キー動作リスク
--agent-stateagent_state = true~/.claude~/.codexなど、エージェント自身のログイン情報と設定。以後、ジェイルの中のものは何でもその認証情報を使えます。1つだけ開ける
--claude-dir <PATH>claude_dir = "..."指定したディレクトリをClaudeの状態保存先として使い、CLAUDE_CONFIG_DIRを設定します。1つだけ開ける
--env <NAME[=VALUE]>なしシェルの変数を1つ渡すか、NAME=VALUEの形で1つ設定します。繰り返し指定でき、ディスクには保存されません。1つだけ開ける
--inherit-envinherit_env = trueシェルの環境全体を、中にある秘密情報ごと渡します。使わないでください。ジェイルを弱める
なしenv_pass = ["NAME"]--envと同じですが、グローバルファイルでのみ有効です。プロジェクトファイルで設定しても無視されます。1つだけ開ける

デスクトップとハードウェア

フラグ設定キー動作リスク
--gpuno_gpu = falseGPUデバイス。同時に、ドライバの攻撃対象領域も開きます。Linuxのみ。1つだけ開ける
--displayno_display = falseWaylandのソケット。セッションのそれ以外のものは渡しません。Linuxのみ。1つだけ開ける
--x11x11 = trueX11のソケット。X11では、プログラムがキー入力を記録したりスクリーンショットを撮ったりできます。ジェイルを弱める
--audioaudio = truePipeWireとPulseAudioのソケットと/dev/snd。ジェイルの中のものは何でも録音と再生ができます。Linuxのみ。1つだけ開ける
--host-shmhost_shm = trueホストの/dev/shm。ジェイルの外のプロセスとの共有メモリが開きます。1つだけ開ける
--picturespictures = true読み取り専用の~/Pictures1つだけ開ける
--browser[=hard|soft]browser_profile = "hard"独立したブラウザプロファイル。hard(デフォルト)は実行をまたいで何も残さず、soft~/.local/share/ai-jail/browsersの下にプロファイルを残します。1つだけ開ける

ファイル

フラグ設定キー動作リスク
--map <PATH|SOURCE:DEST>ro_maps = [...]パスを1つ、読み取り専用で追加マウントします。別の場所にマウントするにはSOURCE:DESTと書きます。繰り返し指定できます。1つだけ開ける
--rw-map <PATH|SOURCE:DEST>rw_maps = [...]パスを1つ、読み書き可能で追加マウントします。繰り返し指定できます。1つだけ開ける
--overlay-map <PATH>overlay_maps = [...]パスをコピーオンライトでマウントします。エージェントの書き込みは別のレイヤーに入り、元のファイルは変わりません。Linuxのみ。macOSでは読み取り専用のマウントになります。1つだけ開ける
--hide-dotdir <NAME>hide_dotdirs = [...]指定したドットディレクトリ(例:.my_secrets)を決してマウントしません。繰り返し指定できます。

無効にできるが、すべきでない層

フラグ設定キー動作リスク
--no-landlockno_landlock = trueカーネル側でファイルのルールを二重に適用するLandlockを無効にします。--lockdownでは拒否されます。ジェイルを弱める
--no-seccompno_seccomp = true危険なシステムコールを止めるフィルターを無効にします。ジェイルを弱める
--no-rlimitsno_rlimits = true暴走したプロセスを抑える制限を無効にします。ジェイルを弱める
--no-private-homeprivate_home = false新しいホームディレクトリを使うのをやめます。本物のホームへの広いアクセスを与えることになります。必要なパス1つだけを--mapで渡すほうが安全です。ジェイルを弱める

各層の役割は仕組みのページで説明しています。

ユーティリティ

フラグ動作
--dry-runサンドボックスコマンドを表示するだけで、何も実行しません。設定ファイルを書くこともありません。
--initプロジェクトの.ai-jailを作成または更新して終了します。
--clean今回の実行では、プロジェクトの.ai-jailを無視します。
--bootstrapAIツール自体の権限設定ファイルを生成します。
status現在の.ai-jailの設定を表示します。
-v, --verboseジェイルの構築中に、すべてのマウントを表示します。

残りのオプションはai-jail --helpで確認できます。ステータスバー、worktree、mise、ターミナル関連です。

プロジェクト内の秘密情報を隠す

.envファイルはプロジェクトの中にあり、プロジェクトは読み書き可能です。ネットワークが有効なら、エージェントはそこで読めるものを何でも外へ送れます。マスクすれば、そうしたファイルを取り除けます。

プロジェクトフォルダの図。エージェントはsrc、package.json、README.mdに届きます。.envファイルはマスクされ、secretsフォルダは拒否されています。どちらも暗く、格子がかかっていて、エージェントからの線は届いていません。
プロジェクトのそれ以外の部分は元のままです。

--mask <PATH|GLOB>

一致したものをすべて空のプレースホルダーに置き換えます。エージェントにはファイルがあることは見えますが、中身は得られません。存在を確認するだけのツールはそのまま動きます。

--deny-path <PATH|GLOB>

一致したものすべてを、アクセスすると権限エラーになるようにします。

--mask-except--deny-path-except

ルールからパスを1つ除外します。保護を弱めるので、プロジェクトファイルでは設定できません。

フラグで指定
# globは引用符で囲む。シェルに展開させず、パターンのままai-jailに渡すためai-jail --mask .env --mask '.env.*' --mask '*.pem' --deny-path secrets/ claude ai-jail --mask '.env.*' --mask-except .env.example claude
.ai-jail
# プロジェクトファイルは厳しくする方向なら設定できるので、リポジトリ内でも使えるmask = [".env", ".env.*", "*.pem"]deny_paths = ["secrets/"]

ロックダウン:変更させたくないコードを読ませる

--lockdownはレビューや監査のためのモードです。エージェントはプロジェクトを読んで質問に答えられますが、ファイルは1つも変更できません。

2枚のパネル。通常モードでは、エージェントは壁の中で、読み書きできるプロジェクトフォルダと/tmpフォルダの隣にいます。ロックダウンでは壁が厚くなり、プロジェクトフォルダは読み取り専用で、書き込めるのは/tmpだけです。
エージェントとプロジェクトは同じで、書き込めるのは一時ディレクトリだけです。

変わる点

  • プロジェクトは読み取り専用でマウントされる
  • Linuxで書き込めるのは/tmpだけ。macOSではどこにも書き込めない
  • ホームのドットディレクトリ、追加のマップ、オーバーレイはすべてなし
  • 環境は空になり、PATHはシステムディレクトリに固定される
  • Landlockが必須になり、適用できなければ起動に失敗する
  • プロセス数、開けるファイル数、ファイルサイズの制限が厳しくなる
  • ほかに何を渡していても、ディスプレイ、オーディオ、GPU、Docker、SSHエージェント、miseは使えない
ターミナル
ai-jail --lockdown claude

レシピ

コピーして使ってください。何が組み立てられるかを確かめるには、先に--dry-runを付けて実行します。

クラウド型エージェントを日常的に使う

ホスト型のモデルには、APIに接続するためのネットワークと、認証のための自身のログイン情報が必要です。両方をグローバルファイルに書いておけば、コマンドは短いままです。

~/.ai-jail
# 最初に一度だけ、~/.ai-jailに[commands.claude]network = trueagent_state = true # 以降は、どのプロジェクトでもai-jail claude

SSH経由でgit pushする

--ssh~/.sshを読み取り専用でマウントし、SSHエージェントのソケットを転送します。pushにはネットワークも必要です。

terminal
ai-jail --network --ssh --agent-state claude

miseのツールチェーン

新しいホームディレクトリにはmiseでインストールしたものがないので、ai-jailはmiseをスキップします。miseの2つのディレクトリを読み取り専用でマップしてください。

~/.ai-jail
[commands.claude]ro_maps = ["~/.config/mise", "~/.local/share/mise"]

エージェント用のブラウザ

--browserだけでは、ページの読み込みもウィンドウの表示もできないブラウザになります。Linuxでは--network--displayも必要です。X11のブラウザなら、--displayの代わりに--x11を使います。

terminal
# Waylandai-jail --browser=soft --network --display chromium# X11ai-jail --browser=soft --network --x11 chromium

Claudeのプロファイルを分ける

実行ごとに別のClaudeディレクトリを指定すれば、仕事用と個人用のログインを分けておけます。

terminal
ai-jail --network --claude-dir ~/.claude-work claude

リスクのあるリファクタリングをコピーで試す

オーバーレイを使うと、エージェントの書き込みはプロジェクト内の.ai-jail-overlaysの下にある別レイヤーに入ります。後で元のファイルと比べて、気に入った変更だけを取り込めます。Linuxのみ。

terminal
ai-jail --network --agent-state --overlay-map ~/Projects/my-app/src claude

古い設定はそのまま動く

後方互換性はプロジェクトのルールで、フラグや設定キーが削除されることはありません。未知のキーは無視され、足りないキーにはデフォルト値が入るので、古いバージョン向けに書いたファイルもそのまま読み込めます。

古いスイッチは、trueで機能が無効になる反転した名前のままです。no_gpuno_dockerno_displayno_miseno_landlockno_seccompno_rlimitsが該当します。--gpuno_gpu = falseとして保存されるのはそのためです。新しいスイッチはnetwork = trueのような素直な名前を使います。

エージェントを檻の中に

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

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