メインコンテンツにスキップ

エージェント封じ込めのベストプラクティス: サンドボックス化(プライベートベータ)

Cyber Verification Program のお客様向けに、API に新しいサンドボックス脱出分類器を提供しており、悪用の監視と削減が可能です。この記事では、自律型エージェントが強力な分離を必要とする理由、リファレンス設計がそれらを分離する方法、およびネットワークアクセスが必要なエンゲージメントのスコープ設定と監督の方法について説明します。

この分類器はプライベートベータ版です。

利用可能なすべてのリソースの概要については、エージェント封じ込めのベストプラクティス: はじめに(プライベートベータ)を参照してください。

概要

  • 自律実行では、人間がエージェントのツール呼び出しを承認せず、エージェントがターゲットコードを実行する可能性があります。自律型エージェントは、ホストとエージェント、ターゲットコードの両方の間にハードウェア仮想化カーネルを配置する強力なサンドボックスで実行することをお勧めします。ベア Docker/runc を使用しないでください。また、--privileged またはホストネットワークを使用しないでください。

  • リファレンス設計は、内部ネットワーク上の独自の microVM(Kata Containers with Firecracker)で各エージェントを実行します。KVM を備えた Linux ホストが必要であり、これはそれを実行できるホストを制限します。Kata は Firecracker が依存するランタイムを廃止しました。

  • 認証情報を保持するパス(~/.aws、~/.ssh、.env など)をエージェントの環境にマウントしないでください。モデル API 認証情報もエージェントの環境から除外してください。代わりに、別の認証情報プロキシがそれを保持し、各モデルリクエストに追加します(認証情報プロキシを参照)。

  • デフォルトでエグレスを拒否します。リファレンス設計では、モデル呼び出しは認証情報プロキシを通過し、エグレスプロキシは許可リストに登録されていない限り、他のすべての宛先を拒否します。

  • 各ホストでサンドボックスをテストしてから依存し、サンドボックスまたはモデルが変更されるたびに再度テストしてください。

  • ネットワークアクセスが必要なエンゲージメントの場合、エージェントの指示でスコープを明記し、ネットワークで強制し、自律型エージェントをライブの高リスク システムから遠ざけてください(スコープと監督を参照)。

サンドボックス化ガイダンス

目指すべきプロパティ

独自のサンドボックスを構築する場合、これらはリファレンス設計が提供するプロパティです。この記事の残りの部分では、それらを取得する 1 つの方法について説明します。

  1. 各エージェントは独自のゲストカーネルを持ち、ホストと共有しません。

  2. エージェントのファイルおよびシェルツールは、ゲストのファイルシステムのみを表示します。ホストディレクトリはゲストに共有されません。

  3. モデル API 認証情報はエージェントの環境またはディスク上にありません。サンドボックス外のプロキシが各リクエストに追加します。

  4. エージェントはインターネットアクセスを持ちません。エグレスはゲスト外で強制され、許可リストに登録されていない限り、すべての宛先が拒否されます。

  5. クラウドメタデータサービスにはエージェントからアクセスできません。

  6. すべてのエージェントにはターン制限があり、設定した場合は時間制限があります。

  7. 特権モード、追加機能、デバイスパススルー、またはホストネットワークはありません。

  8. オーケストレーターは信頼できるホスト上で実行され、トランスクリプトをそこに書き込みます。

一般的なガイドライン

強力なサンドボックスは、エージェントがターゲットコードを実行し、人間が各アクションを承認しない自律実行で最も重要です

自律型エージェントを強力なサンドボックスで実行し、そのサンドボックス内のプロセスが引き起こす可能性のある副作用を検討してください。フロンティアモデルは、制限を回避するための創造的なパスを見つけるのにますます優れています。脆弱性ハンターとして効果的にするのと同じプロパティは、独自の実行環境に対して予期しないアクションを実行する可能性があることを意味します。これは仮説的ではありません。Anthropic は、タスクを完了するために弱い制約を回避するモデルの例を公開しています(How we contain Claude across productsを参照)。

具体的には、ベア Docker/runc で自律脆弱性検出エージェントを実行しないでください。特に --privileged またはホストネットワークを使用しないでください。標準コンテナはホストカーネルを共有するため、コンテナ内のカーネルエクスプロイトはホスト侵害です。ターゲットコードとホストの間にハードウェア仮想化カーネルを配置することをお勧めします。これは、エージェントを仮想マシンで実行することを意味します。それが不可能な場合は、他に何も保持しない専用ベアメタルホストを使用してください。独自のサンドボックスを構築する場合、Linux では Firecracker、Windows では Hyper-V、macOS では Hypervisor フレームワークに基づく VM をお勧めします。リファレンス設計は Firecracker を使用します。

サンドボックスからのすべてのエグレスをブロックします。エージェントはモデル API に認証情報を追加して実行し、サンドボックス外で実行するプロキシを通じてのみ到達するため、サンドボックスは API ホストへの直接ルートを必要としません。すべてのツール、パッケージ、および依存関係を実行開始前にインストールして、実行中に何もフェッチする必要がないようにしてください。

ループ内に人間がいるインタラクティブな使用は、一般的にリスクが低いですが、それでもサンドボックスをお勧めします。ラップトップの Claude Code からエージェントをインタラクティブに駆動する場合、すべてのツール使用をレビューするか(手動モード)、自動モード許可分類器に依存して、リポジトリの外に到達するすべてのアクションを人間が承認してください。自動モードはルーチン許可プロンプトを削除します。読み取りと作業ディレクトリの編集を自動的に承認し、他のすべてを破壊的、不可逆的、またはオフタスクアクションをブロックすることを目的とした背景分類器に送信します。これはベストエフォート チェックです。見落とす可能性があり、セキュリティ作業では正当なステップを拒否することもあります。自動モードは、その仕組み、期待できることの詳細、および環境用に設定する方法について説明しています。

~/.aws、~/.ssh、.env などの認証情報を含むパスをエージェントの環境にマウントしないでください。エージェント独自のモデル呼び出しが使用する認証情報についても同じです。サンドボックスの外に保持し、エージェントが読み取ることができないプロキシが各リクエストに追加します(認証情報プロキシを参照)。エージェントを MCP サーバーまたはメール、クラウドストレージ、本番インフラストラクチャなどの外部状態への書き込みアクセス権を持つツールに接続しないでください。

各実行をセットアップフェーズと攻撃フェーズに分割し、異なるネットワークポリシーを使用します

これは上記のガイドラインを実践に移す 1 つのパターンです。セットアップフェーズはアウトバウンドインターネットアクセスを備えており、すべてのツール呼び出しを承認するループ内に人間がいます。エージェントは依存関係をプルし、ターゲットをビルドし、仕様ドキュメントからサンドボックスを立ち上げます。攻撃フェーズは一般的なインターネットアクセスを持ちません。すべてのエグレスは許可リストプロキシを通過し、エンゲージメントで指定されたホストのみを許可するため、プロキシはスコープも強制します。モデル呼び出しは別の認証情報プロキシを通過します。エージェントはターゲットを無人で調査できます。プロキシはエージェント独自のトラフィックを含みます。ネットワークターゲットがエージェントの代わりに送信するトラフィックは含みません。

エージェントが繰り返し必要とする依存関係をセットアップイメージに焼き込み、攻撃フェーズの実行がインターネットアクセスをまったく必要としないようにします。ターゲットごとに認証情報をスコープし、1 つのターゲットで作業しているエージェントが別のターゲットに対して使用できないようにします。攻撃フェーズ中にサンドボックス内で Claude Code の自動モードをオンに保ち、サンドボックスをその分類器に説明します。自動モードを参照してください。

各実行を制限し、オフスイッチを知ってください

すべてのエージェントに明示的な予算を与え、意図したテストを超える実行が誰かが気付いたときではなく、それ自体で停止するようにします。すべてのエージェントにハードターン制限を強制します。エージェントがそれを使い果たしたら、実行を終了し、ターンを自動的に付与しないでください。より高い制限で再起動することは、人が続行することを決定する時点です。実行を時間でも制限します。時間制限を超えるセッションを同じ方法で終了します。実行は最終的であり、再開されることはなく、制限が長時間実行コマンドの途中に到達した場合でも、エージェントプロセスは停止されます。制限が読み取ることができない値に設定されている場合、無制限で実行する代わりに起動を拒否します。エンゲージメント用に意図的に制限を設定し、寛容なデフォルトを受け入れないでください。エージェントトランスクリプトのオフライン監視の監視ケイデンスとペアにして、長いバッチが最後だけでなく 1 時間または 2 時間ごとに確認されるようにします。バッチを停止せずに単一のエージェントを停止する方法を知ってください。Docker ベースのセットアップでは、docker rm -f <agent-container> です。オーケストレーターはその実行を失敗として記録し、バッチの残りを続行する必要があります。

詳細については、2 つの Anthropic リソースを参照してください。AI エージェントの安全なデプロイは、分離オプション、認証情報プロキシ、およびファイルシステムの強化について説明しています。エンジニアリング回顧How we contain Claude across productsは、これらの同じメカニズムが本番環境で実行されたときに何が機能し、何が機能しなかったかについて説明しています。

スコープと監督

サンドボックスはエージェントが到達できるものを制限します。ペンテスト、レッドチーミング、およびネットワークアクセスが必要なその他のエンゲージメントの場合、以下のプラクティスはエージェントが求められ、許可されることを制限します。これらはターゲットとチームに依存するため、ツールはそれらのほとんどを実装することはできません。

エージェントの指示でスコープを明記します

実行前に、スコープ内のターゲット、許可されたアクション、ネットワーク境界の場所、およびスコープ外のものをエージェントに伝えます。各制約を意図として(「10.0.3.0/24 の外のホストにアクセスしないでください」)、環境に関する主張ではなく(「インターネットに到達できません」)、環境が誤って設定されている場合でも指示が成立するようにフレーズします。サンドボックス化されたローカル作業についても同じことを行います。サンドボックスがそれをブロックしていても、エージェントにインターネットアクセスを使用しないように伝えます。自動モードの分類器に提供する説明は別のものです。マシンに関する事実を述べています(自動モードを参照)。

ネットワークで同じスコープを強制します

可能な場合は、上記で説明した同じ分離内でエージェントを実行し、スコープ内のターゲットのみへのエグレスを許可リストに登録します(エグレス許可リストを参照)。エージェントはモデル API に認証情報プロキシを通じてアクセスし、許可リストを通じてはアクセスしません。利用可能な場合は、本番環境から切断されているステージング環境またはレプリカ環境にエンゲージメントを指定します。

可能な場合はターゲットへのアクセスをブローカーします

アクセスプロキシまたは定義されたツールセットなど、観察できるものを通じてターゲットシステムへのアクセスをエージェントに提供します。エージェントがターゲットへの一般的なアクセス権を持つ独自のツールを作成できないようにしてください。カスタムハーネスでは、読み取り専用ツールを状態を変更するツールから分離し、2 番目のグループをより厳密に監督します。リスクの高いコマンドを提案されたときに分析し、それらを拒否するか、人にエスカレートすることを検討してください。

ネットワークアクセスを持つ実行を監督します

エンジニアが実行を監視し、ツール呼び出しとネットワークアクティビティに従い、実行をすぐに停止できることをお勧めします。エージェントはマシン速度で動作するため、ライブ観察は、アクション実行前に機能する制御(ネットワーク許可リスト、ブローカーツール、状態変更アクションのレビュー)を補完します。それらを置き換えません。継続的な注意が実用的でない長時間または自律実行の場合、ソフトウェアで継続的に監視します(エージェントトランスクリプトのオフライン監視を参照)。

自律型エージェントをライブの高リスク システムから遠ざけてください

スコープ外のアクションが OT/ICS、医療、エネルギーシステムなどの重要なサービスの安全性または可用性を危険にさらす可能性があるライブ本番システムに対して自律型エージェントを実行しないでください。これはすでにそのようなシステムの人間主導のテストの規範であり、ここでも同様に適用されます。レプリカ、テストベッド、またはデジタルツインに対してテストするか、計画された停止中にテストしてください。ライブアクセスが避けられない場合は、エージェントをパッシブまたは読み取り専用アクティビティに制限し、人が状態変更ステップを実行してください。

依存する前にサンドボックスをテストしてください

ホストから実際のエンゲージメントを実行する前に、以下の 2 つのステップでサンドボックスをテストしてください。最初の実際の使用前に、およびモデルまたはサンドボックスを変更するたびにこれを行います。サンドボックスの変更には、新しいホスト、ハイパーバイザーまたはコンテナランタイムの新しいバージョン、異なるネットワークまたはプロキシセットアップ、および編集されたコンテナまたはコンポーズ設定が含まれます。

まず、Claudeに設定を確認させます

ホスト上のインタラクティブなClaude Codeセッションで、このマシンに設定されているサンドボックス設定を読み取り、この記事で説明されている境界を弱める可能性のあるものを報告するよう指示します。以下を指定します:

  • ハイパーバイザーとコンテナランタイム設定(参照設計の場合、Kataのレンダリングされたconfiguration.tomlとDockerのdaemon.json);

  • エージェントのネットワークとランタイムが報告するエグレスプロキシ、およびプロキシのアローリスト;

  • ランタイムが報告する認証情報プロキシ、および実行中のエージェントコンテナの環境(以下の認証情報プロキシを参照);

  • エージェントまたはターゲットを開始するコンポーズまたはオーケストレーションファイル;

  • ゲストにマウントまたはストリーミングされるものの一覧(以下の運用上の注意を参照)。

このステップは設定と状態のみを読み取ります。エージェントを起動しません。

次に、監視下での脱出テストを実行します

テストエージェントを本番環境のエージェントと同じ方法で起動し、手動で構築したコマンドではなく、テストが実際のパスを実行するようにします。以下の分離を自分で確認するセクションでは、代わりに境界の手動チェックについて説明しています。エージェントに単一のタスクを与えます:境界外の何かに到達しようとし、何かが成功したらすぐに停止して報告します。プロンプトで境界を具体的に名前付けします:ホスト、他のコンテナ、コンテナランタイムソケット、クラウドメタデータサービス、およびプロキシのアローリストにないホスト。これは人間による厳密な監視下でのみ実行し、モデルAPIを超えてインターネットアクセスがないホストで実行し、再構築する準備ができているホストで実行して、脱出が成功しても損害が発生しないようにします。ベアメタルの場合、テストを使い捨てVM内で実行します。クラウドVMの場合、新しいインスタンスを使用し、その後破棄します。セッションの実行中に監視します。成功を阻止要因として扱います:ホストを修正し、テストを繰り返し、テストが成功するまでそのホストからエンゲージメントを実行しないでください。

その後、トランスクリプト全体を読みます

エージェントが試したことと、それが外に出たかどうかを確認します。プロキシを通過しなかった直接接続、認証情報ファイルまたはメタデータアドレスの読み取り、コンテナランタイムソケットの使用または隣接するコンテナのプローブ、コンテナ自体のファイルシステム外への書き込み、およびエージェント自体の設定またはツールの変更の試み。テストは、トランスクリプトがこれらのそれぞれが試行され、予想される理由で失敗したことを示すときに合格します。それぞれについて、サンドボックスまたは権限分類器がそれを停止したかどうかを記録します。分類器が拒否した試みはサンドボックスに到達しなかったため、手動チェックでカバーしてください(以下の分離を自分で確認するを参照)。合格テストは最小限のバーであり、分離の証明ではありません。

不可能なタスクを避け、失敗した実行を最初に確認します

起動前に、タスクが指定されたとおりに完了できることを確認します。完了できないタスクの例:見つけるものがないフォーカス領域、到達不可能なターゲット、存在しないバグ、またはタスクに必要なインストールされていないツール。セットアップを変更するか、新しい種類のタスクを開始するたびに、起動前にターゲットがビルドでき、到達でき、エージェントが必要なツールを持っていることを確認します。同じ理由で、バッチを確認するときは、成功したものの前に、失敗したか何も見つからなかった実行のトランスクリプトを読みます。

分離を自分で確認する

各ホストでこれらのチェックを手動で実行します。2番目の列は参照設計(KataランタイムとFirecrackerを備えたDocker)のチェックについて説明しています。独自のランタイムに適応させます。

確認すること

方法

予想される結果

別のゲストカーネル

サンドボックス化されたコンテナとホストでuname -rを実行します

2つのバージョンが異なります

VMモニターはホストで監禁されています

実行中のコンテナについて、Firecrackerプロセスを検査します:そのルートディレクトリ、/proc/<pid>/statusのSeccompとNoNewPrivs、そのマウントとネットワークネームスペース、およびそのcgroup

VMのファイルのみがそのルートの下にあります。Seccomp: 2とNoNewPrivs: 1。両方のネームスペースはホストのものと異なります。cgroupパスはコンテナに名前を付けます

ホストファイルは内部に表示されません

ホストにファイルを作成し、サンドボックス化されたコンテナから読み取ってみます

見つかりません。これは、どのランタイムでも合格すべき基本的なチェックです

エグレスが拒否されます

エージェントコンテナから、エグレスプロキシを通じてモデルAPIホストと別の公開ホストをリクエストします

両方が拒否され、エグレスプロキシは各行の拒否行をログに記録します。エージェントはモデルに認証情報プロキシを通じてのみ到達します

エージェントコンテナに認証情報がありません

実行中に、エージェントコンテナの環境をプロバイダー名でフィルタリングしてリストします

プレースホルダー、認証情報プロキシのアドレス、およびプロバイダー設定。実際のキー、トークン、または認証情報ファイルはありません

参照設計

このセクションでは、参照実装が上記のガイダンスをどのように満たしているかについて説明します。実装は含まれていません。コピーできる設計として読んでください。

各エージェントがどのように分離されるか

すべてのエージェントは、ターゲットバイナリとソースの隣にある独自のmicroVM内でclaude -pとして実行されます。microVMは、Kata Containersコンテナであり、Firecracker仮想マシンモニターによってサポートされ、Dockerにランタイムとして登録されています。エージェントのRead、Write、およびBashツールは、そのゲストのファイルシステムとカーネルのみを参照します。

ゲストとホスト間の接続は意図的に小さいです。これはKVMと、Firecrackerがエミュレートする少数の仮想デバイスで構成されています:コンテナのディスク用のブロックデバイス、1つのネットワークインターフェース、およびKataがゲスト内でプロセスを開始するために使用するvsockコントロールチャネル。Firecrackerプロセス自体はホストで制限されています。これは「jail」で実行されます。これは、そのVM のファイルのみを保持するchrootディレクトリであり、独自のマウントネームスペース、コンテナのネットワークネームスペース、およびFirecrackerの組み込みseccompフィルターを備えています。これはコンテナのcgroupに計上されます。ホスト側で信頼するのはKVM、Firecracker、およびKataのランタイムプロセス(Dockerが通信するコンテナごとの「shim」で、rootとして実行されます)です。

オーケストレーターは信頼できるホストに留まります。これはコンテナのライフサイクルを管理し、トランスクリプトをストリーミングし、docker execでファイルを出し入れします。これはKataがゲスト内のエージェントを通じて提供します。ランチャーはこのサンドボックス内でのみエージェントを開始します。エージェントが開始される前に、サンドボックスランタイムが登録されていること、/dev/kvmが存在すること、およびエグレスプロキシが稼働していることを確認し、そうでない場合は実行を拒否します。

サンドボックスが各サーフェスに対して何を変更するか:

サーフェス

サンドボックスなし

サンドボックスあり

エージェントRead/Write

ホストファイルシステム

ゲストファイルシステムのみ(コンテナ独自の仮想ディスク、ゲストカーネルの下)

エージェントBash

ホストシェル

ゲストシェルのみ(ゲストカーネル;ホストはKVMとFirecrackerの仮想デバイスを通じてのみ到達可能)

ネットワーク出力

ホストが持つもの

インターネットアクセスなし。モデル呼び出しのみ、認証情報プロキシ経由

モデルAPI認証情報

エージェントの環境内

エージェントコンテナ内ではなく、別の認証情報プロキシコンテナで保持(下記の認証情報プロキシを参照)

ホスト結合

完全

docker execでファイルの入出力を行い、ゲスト内のKataのエージェントで提供。読み取り専用入力はコンテナ起動時に取得されたコピーとして到着。実行中に変更されるファイルはオーケストレーターによってストリーミング配信

権限チェック

オートモード分類器のみ

オートモード分類器とマイクロVM境界(オートモードを参照)

各プロパティが適用される場所:ハードウェア仮想化がカーネルとファイルシステムの境界を提供します。エージェントのRead/Write/Bashはゲストカーネルに対して実行され、その背後にあるFirecrackerプロセスはホスト上でジェイルされ、seccompで制限されています。出力ポリシーはVM のネットワークインターフェースのホスト側で適用され、Docker--internalブリッジ(デフォルトルートなし)とそのネットワーク上の2つのプロキシによって実行されます。認証情報プロキシはモデル呼び出しのみを転送し、他は転送しません。出力プロキシは他のすべての宛先を拒否します。許可リストが空で、追加しない限り、トラフィックはゲスト自身のネットワークスタックを通じて出ていき、フィルタリングは2つのプロキシで行われます。

認証情報プロキシ

モデルAPI(APIキー、OAuthトークン、AWSまたはGoogle認証情報)の認証情報は、エージェントコンテナに配置されることはありません。ホスト上のオーケストレーターがそれを読み取り、検証し、各起動時に1つの小さな追加コンテナ(認証情報プロキシ)を開始してそれを保持します。プロキシはエージェントの内部ネットワークに接続され、エージェントコンテナはモデル呼び出しをそこに送信します。claude CLIはプロキシのアドレスをAPIベースURLとして取得し、キーまたはトークンが通常ある場所に固定プレースホルダー値を取得します。これはプロキシを通じてのみモデルAPIに到達し、サンドボックスの外からAPIキーが注入されるというベストプラクティスに従っています。リファレンス設計では、プロキシはエージェント自身のlocalhost上のプロセスではなく、エージェントのネットワーク上の別のコンテナです。すべてのリクエストについて、プロキシは:

  1. 起動が設定された1つのプロバイダーエンドポイントへのモデル呼び出し以外のものを拒否します(他のパスとホストは403とログ行を取得)。

  2. コンテナが送信した認証ヘッダーを削除します。

  3. 実際の認証情報を追加します。APIキーヘッダー、ベアラートークン(プロキシがトークンが短命の場合は自身で更新)、または正確なリクエストで計算されたAWS SigV4署名。

  4. リクエストをプロバイダーにHTTPS経由で転送し、証明書検証を行い、レスポンスをストリーミング配信します。

侵害されたエージェントコンテナの場合、読み取り、コピー、または送信するキー、トークン、または認証情報ファイルはありません。クラウドメタデータサービスもコンテナからは到達不可能です。コンテナが依然として実行できることは、実行が続く限り、あなたのアカウントでプロキシを通じてモデル呼び出しを行うことです。そのため、エージェント実行には狭くスコープされた認証情報を使用し、トランスクリプトが予期しない動作を示す実行後に回転させることをお勧めします。プロキシはリクエストごとに1行をログに記録し、クライアントアドレス、メソッド、パス、ステータス、サイズを含みます。ヘッダーまたはボディはログに記録しません。実行終了時にそのログを保存します(エージェントトランスクリプトのオフライン監視の保持セクションを参照)。

エージェントがモデルAPIに送信するものはすべてネットワークを離れ、プロキシが検査またはログに記録しないリクエストボディ内にあります。

認証ルートごとに各側が保持するもの:

ルート

認証情報プロキシが保持するもの

エージェントコンテナが取得するもの

APIキー

キー

プロキシアドレス + プレースホルダーANTHROPIC_API_KEY

OAuthトークン(claude setup-token)

トークン

プロキシアドレス + プレースホルダーCLAUDE_CODE_OAUTH_TOKEN

ワークロードアイデンティティフェデレーション(WIF)

アイデンティティトークン、およびプロキシがそれと交換してリフレッシュするアクセストークン。ANTHROPIC_IDENTITY_TOKEN_FILEの場合、トークンファイルのディレクトリはプロキシに読み取り専用でマウントされるため、プロキシはローテーションされたトークンを見ます。インラインANTHROPIC_IDENTITY_TOKENの場合、プロキシはその値を保持し、再読み込みするファイルはありません

プロキシアドレス + プレースホルダーCLAUDE_CODE_OAUTH_TOKEN

ant auth loginプロファイル

プロファイルディレクトリ、プロキシに読み取り専用でマウント

プロキシアドレス + プレースホルダーCLAUDE_CODE_OAUTH_TOKEN

Bedrock

ベアラートークン、またはアクセスキーセット(プロキシが各リクエストに署名)

プロキシアドレス、CLAUDE_CODE_SKIP_BEDROCK_AUTH=1、リージョン。AWS認証情報なし

Vertex

サービスアカウントキー、およびプロキシがそれからミントしてリフレッシュするアクセストークン

プロキシアドレス、CLAUDE_CODE_SKIP_VERTEX_AUTH=1、リージョンとプロジェクト。Google認証情報なし

認証情報プロキシコンテナはセットアップの信頼できる側の一部です。サンドボックスランタイムではなくプレーンruncで実行され、マウントされたファイルを読み取るために必要な1つの機能を除いてすべての機能がドロップされたrootで実行され、読み取り専用ファイルシステムを持ちます。エージェントの内部ネットワーク上のそのアドレスのみでリッスンし、出力プロキシを通じてではなくプロバイダーに直接接続します。オーケストレーターはdocker exec経由で実行中のプロキシに認証情報を渡します。WIFトークンファイルとプロファイルルートの場合、トークンまたはプロファイルを保持するディレクトリはプロキシに読み取り専用でマウントされ、プロキシはそこからファイルを読み取ります。認証情報はプロキシコンテナの環境またはコマンドラインにないため、docker inspectはシークレットではなくマウントを表示します。

起動ごとに1つのプロキシを開始し、実行が終了または中断されたときに削除します。キルされた実行によって残されたプロキシをチェックし、次の起動前に削除します。

認証情報プロキシには2つの副作用があります。まず、エージェントのCLIにはデフォルト以外のAPIアドレスが与えられるため、デフォルトアドレスにのみ適用される少数のCLI機能はエージェントコンテナ内でオフになります。テレメトリと更新チェックもオフになります。どちらにしろ出力ルートがないためです。次に、Vertexではプロキシのパスフィルターが、エージェントコンテナが残りのVertex AI APIを使用するのを防ぐ主な制御です(出力許可リストを参照)。起動時のキーのIAMスコープのチェックは2番目のレイヤーです。

出力許可リスト

出力プロキシの許可リストはデフォルトで空です。エージェントコンテナはモデルAPIに認証情報プロキシを通じてのみアクセスします(認証情報プロキシを参照)。各起動は認証情報が選択するプロバイダーのそのプロキシを開始するため、プロバイダー固有のものはサンドボックスセットアップに保存されません。エージェントが出力プロキシを通じてリクエストする他のすべての宛先(モデルAPIホスト自体を含む)は403とそのログの拒否行を取得します。Bedrockおよびvertexエンドポイント(AWS_REGION、CLOUD_ML_REGION)を選択するリージョン値は、使用される前に厳密なパターンに対してチェックされるため、不正な形式の値が認証情報を別のホストに送信することはできません。

Vertexには注意すべき1つの制限があります。…aiplatform.googleapis.comはVertex AI API全体を提供するため、カスタムジョブを作成できる認証情報は、プロジェクト内で完全なインターネット出力を持つ任意のコンテナを実行できます。これに対して2つの制御を使用します。認証情報プロキシが設定されたプロジェクト(…/publishers/anthropic/models/…:rawPredict、:streamRawPredict、および:countTokens)でのみパブリッシャーモデル呼び出しを転送し、他のすべてのパスを拒否するようにします。起動時にキーのIAMスコープをチェックし、閉じた状態で失敗します。gcloud ユーザーADCを拒否し、testIamPermissionsでサービスアカウントキーをチェックし、ワークロード作成権限を保持している場合は拒否します。アカウントにaiplatform.endpoints.predictのみを保持するカスタムロールを付与します。メタデータサーバー、Googleの STS、およびIAM認証情報エンドポイントはエージェントコンテナからは到達不可能である必要があります。

エージェントがパッケージミラーやスコープ内のターゲットなどの追加ホストに到達する必要がある場合は、それらを出力プロキシの許可リストにhost:portエントリとして追加します。エンゲージメントが必要とするもののみを追加します(スコープと監督を参照)。

このリストにmodel-APIホストを追加しないでください。エージェントはそれを必要としません。なぜなら、モデル呼び出しは認証情報プロキシを経由するためです。追加すると、エージェントコンテナがAPIへの直接ルートを取得し、設計の残りの部分(権限分類器に伝えられる内容を含む)は、それらが存在しないことを前提としています。

許可リストを変更すると、エグレスプロキシが再起動され、ライブエージェント接続がドロップされます。バッチ中ではなく、バッチ間で実行し、その後、プロキシが読み込んだリストを確認してください。

認証情報設定からプロバイダーエンドポイントを導出し、ホストに設定されているANTHROPIC_BASE_URLなどのベースURL変数は無視してください。認証情報プロキシは常に、認証情報が選択するエンドポイントに転送する必要があります。

このようなサンドボックスの構築と運用

このセクションは、リファレンス実装でKataとFirecrackerの下でエージェントを実行することから学んだことをまとめています。インストール手順のセットではありません。

ホスト要件

リファレンス設計には、物理Linuxマシン、またはそれ自体がVMを実行できるVMが必要です。

  • Linux x86_64またはaarch64(KVM対応)(/dev/kvmが存在し、使用可能):ベアメタル、またはネストされた仮想化が有効なクラウドVM。

    • GCE、Azure、およびAWSは、選択されたインスタンスタイプでネストされた仮想化を提供します(AWSの場合、例えば、C8i、M8i、およびR8iファミリー)。AWSベアメタル(*.metal)インスタンスも機能します。

    • ネストされた仮想化はパフォーマンスに多少の影響を与えます。境界を弱めることは予想されていません。

  • コンテナ用のブロックデバイスストレージ。Firecrackerはホストディレクトリをゲストに共有できません。VMに接続できる唯一のストレージはブロックデバイスです。したがって、コンテナルートファイルシステムは、通常のオーバーレイファイルシステムではなく、ブロックデバイスとして存在する必要があります。Dockerの場合、containerdのdevmapperスナップショッターがそれを提供します。rootful Docker(リファレンス設計はEngine 25以降を使用)が必要で、システムcontainerd(2.0以降)によってサポートされます。

  • ホストとイメージを構築している間のアウトバウンドネットワークアクセス。エージェントはこのエグレスを取得しません。

以下では機能しません。

  • コンテナまたはKubernetesポッド(Docker-in-DockerおよびコンテナベースのCIランナーを含む)。ホストのcontainerd、Dockerデーモン、およびデバイスマッパーはコンテナ内から設定できず、KVMも通常そこでは利用できません。

  • rootless Docker。

  • ネストされた仮想化のないVM。これはほとんどの汎用クラウドインスタンスタイプです。ただし、それを提供し、有効にするものを選択する場合を除きます。

  • macOSまたはWindows(Docker DesktopおよびWSL2を含む)。

リファレンス設計はmacOSまたはWindowsホストをサポートしていません。

そのサンドボックスはLinuxホスト上のKVMが必要です。Mac上のDockerは、ユーザーのホームディレクトリをマウントしてDockerデーモンを保持する共有Linux VM内で実行されるため、エージェントごとのハードウェア分離を提供できません。Macで作業する場合は、KVM(ベアメタル、またはネストされた仮想化を備えたクラウドVM)を備えたLinuxホスト上でエージェントを実行し、SSHで駆動します。macOSまたはWindows上で独自のサンドボックスを構築する場合は、上記の一般的なガイドラインセクションに記載されているハイパーバイザーを参照してください。

Dockerのイメージストアを切り替えると副作用があります。

Dockerの以前のストアで作成されたイメージとコンテナは、devmapperスナップショッターへの切り替え後、Dockerに対して見えなくなります。ディスク上に残ります。再度表示するには、両方のストレージ設定をdaemon.json(storage-driverおよびfeatures.containerd-snapshotter)に戻し、Dockerを再起動してください。

Kata設定

Kataリリースをピン留めし、インストール前にそのダイジェストを確認してください。リファレンス設計はKataのFirecrackerプロファイルから開始し、/etc/kata-containers/configuration.tomlでこれらの設定をピン留めします。

設定

値

理由

jailer_path

Kataのjailerバイナリへのパス

Firecrackerをそのジェイル内で起動します。ジェイルはVM専用ファイル、独自のマウント名前空間、コンテナのネットワーク名前空間、およびFirecrackerのseccompフィルターのみを含むchrootです。設定されていない場合、KataはジェイルなしでFirecrackerを実行します。

enable_annotations

[]

コンテナはOCIアノテーションを通じてハイパーバイザー設定を変更できません。

disable_guest_seccomp

false

コンテナのDockerのseccompプロファイルもゲスト内に適用され、VM境界の下の2番目のレイヤーです。

sandbox_cgroup_only

true

FirecrackerとそのI/Oスレッドはコンテナのcgroupに配置されるため、VMはコンテナに計上されます。コンテナの--memory制限がVMもキャップするかどうかはホストに依存します(サイジングを参照)。

static_sandbox_resource_mgmt

true

Firecrackerは実行中のVMにCPUまたはメモリを追加できないため、VMはブート時にコンテナの制限から一度サイズ設定されます。

default_vcpus / default_memory

4 / 4096 MiB

VM単位のベースライン。コンテナの--memoryは上に追加されます。ビルド集約的なターゲットの場合は引き上げてください(FirecrackerはVM単位で最大32 vCPUを許可します)。

debug_console_enabled, enable_debug

false

ゲストへのコンソールなし、ホストログのゲストコンソール出力なし。

[factory] enable_template

false

オフ。VM テンプレートはVM間でゲストメモリページを共有するため。

entropy_source

/dev/urandom

ゲスト用のノンブロッキングホストエントロピー。

Kataリリースに付属するkernel、image、kernel_paramsの値はそのまま保持されます。

ゲストカーネルとイメージを不変にする

すべてのVMは同じ2つのファイルからブートし、Kataはそれらをすべてのジェイルにバインドマウントし、jailerはrootとして起動されるため、通常のファイルパーミッションでは、侵害されたFirecrackerプロセスが後続のすべてのVMがブートするイメージを上書きするのを防ぐことはできません。両方に不変フラグを設定します(chattr +i)。そのフラグをクリアするにはシステムコールが必要ですが、Firecracker のseccompフィルターはそれを許可しません。これはジェイル内のrootでさえそれを行うのを防ぐように設計されています。新しいKataリリースをインストールする前に、フラグを自分でクリアしてください。chattrサポートのないファイルシステムでは、代わりに読み取り専用バインドマウントを使用してください。

サイジング

メモリ

各エージェントVMはブート時に1回サイズ設定されます:default_memoryにコンテナの--memoryを加えたもの。4096 MiBのベースラインと4gコンテナ制限では、エージェントは8 GiBのVMです。ホストはゲストが使用するにつれてそのメモリをVMに割り当てます。ブート時にすべてではなく、同時実行エージェントあたりの全量を計画してください:10個のエージェントを並列実行すると80 GiBに向かって増加する可能性があります。コンテナの--memory制限がVM全体をキャップするかどうかは、ホストのcgroupsがどのようにレイアウトされているかによって異なります。ホストに適用されるものを確認してください:

  • コンテナ制限はVM全体に適用されます。エージェントはVM名目上より大きいにもかかわらず--memoryより多くのホストメモリを使用できず、制限を超えるVMはホスト側から強制終了されます。

  • ホスト上のものはVMをブートサイズ以下にキャップしません。エージェントのメモリ使用量はVMサイズ(default_memory + --memory)とゲストカーネル自体のアウトオブメモリキラーによって制限されます。

  • 親cgroupがそれを別の値でキャップします。

このビヘイビアをすべての種類のホストで確認していません。いずれにせよ、VMサイズでホストをサイズ設定してください。

CPU

各VMはdefault_vcpusを取得します。Firecracker は実行中のVMにCPUを追加できないため、ビルド集約的なターゲットの場合は起動前に値を上げてください。最大値はVM あたり32です。

ディスク

すべてのイメージとすべてのコンテナは、イメージストアをバックアップするデバイスマッパーシンプールから仮想ディスクを取得します。プールがいっぱいになると、コンテナ内の書き込みはI/Oまたはスペース不足エラーで失敗します。プールを保持するファイルシステムがまずいっぱいになると、プールは読み取り専用になり、その上のすべてのコンテナが失敗します。docker rmiとdocker system pruneで空き容量を解放します(解放されたブロックはプールに戻ります)。sudo dmsetup status <pool>は使用状況を表示します。長期間のホストの場合、専用ディスク上のLVMシンプールがより良いレイアウトです。

ブート時間

すべてのエージェント開始はゲストカーネルをブートします。ベアメタルでは1秒未満、ネストされた仮想化では数秒かかります。これはエージェント実行時と比較して小さいです。

ホストの強化

  • このジョブにホストを専用にします。

    • エージェントがそれ上のすべてを読むことができると想定し、エージェントが必要とするモデルAPI認証情報以外の認証情報または機密データをそこに保持しないでください。

  • エージェントのトラフィックが接触するすべてのレイヤーをパッチ適用した状態に保ちます。カーネルだけでなく、Docker、プロキシコンテナのベースイメージ、およびホストとモデルAPI間のファイアウォールまたはネットワークアプライアンスです。古いプロキシまたはサンドボックス境界上のファイアウォールはそれ自体が攻撃面です。

  • カーネル、KVM、およびCPUマイクロコードを最新の状態に保ち、カーネルのCPU脆弱性軽減策をデフォルトのままにしておきます。

    • grep . /sys/devices/system/cpu/vulnerabilities/*はVulnerable行を表示しないはずです。

    • ホストが互いに観察してはいけないワークロードと共有されている場合は、Firecracker の本番ホストセットアップガイドのSMTおよび推測実行設定に従ってください。

  • スワップを無効にします(sudo swapoff -a、および/etc/fstabから削除します)。ゲストメモリがスワップに書き込まれないようにするためです。

  • /dev/kvmはワールド書き込み可能である必要はなく、Kataのインストールおよびランタイムディレクトリはrootが所有し、他のユーザーが書き込み可能にしてはいけません。

    • root:kvmモード0660は/dev/kvmに十分です。Kataのランタイムはrootとして実行されるためです。

  • エージェントコンテナまたはターゲットサービスに--privileged、--device、--cap-add、またはホストネットワークを追加しないでください。

    • Kataの下では、これらのフラグはホストデバイスと権限をVMに渡します。

  • エージェントを2つのプロキシの背後にある内部ネットワークに保ちます。

    • Firecracker は独自のパケットフィルタリングを行いません。ホスト側のネットワークとプロキシが出口制御です。

  • トラブルシューティング以外はenable_debugをオフに保ちます。デバッグログにはゲストコンソール出力が含まれます。

新しいホストの検証

新しいマシンをセットアップした後、このシーケンスはサンドボックスがエンドツーエンドで機能することを示します。ステップ3と4は実際のモデルコールを行います。

  1. 分離を自分で検証するの下で分離チェックを実行します。2つのカーネルバージョンは異なる必要があります。コンテナメモリ制限がVMをキャップするかどうかに注意してください(サイジングを参照)。

  2. 使用するイメージで、サンドボックスランタイムの下でエージェントCLIが実行されることを確認します。

  3. 境界をテストします:Claudeにサンドボックス構成をレビューさせてから、サンドボックスに依存する前にテストしますで説明されているように、監視されたエスケープテストを実行します。

  4. 小さいバッチをエンドツーエンドで実行します。既知のターゲットに対して実行します。このステップを実際のエンゲージメントに使用する認証情報モードで実行します。スタンドイン API キーではなく:認証情報プロキシは各モードを異なる方法で処理します(WIFのトークン交換、Bedrockの署名、Vertexのトークンミント)。このランはエンドツーエンドで機能することを確認します。その後、認証情報プロキシのログを確認してください。

  5. 何も残されていないことを確認してください。バッチが完了したら、エージェントコンテナ、ヘルパーコンテナ、VMプロセス、または認証情報プロキシは残っていないはずです。出口プロキシのログはステップ1と3からのプローブ以外の拒否行を表示しないはずであり、認証情報プロキシのログはモデルコールのみを表示するはずです。

運用上の注記

Firecracker を使用してKataの下でエージェントを実行することは、プレーンコンテナを実行することとこれらの点で異なります。

バインドマウントはコピーです。ライブファイルはストリーミングする必要があります

Firecracker にはホストファイルシステム共有がないため、Kataはバインドマウントされたファイルまたはディレクトリをコンテナ起動時にゲストにコピーし、後のホスト上の変更は内部に表示されません。これは、ターゲットソースなど、実行中に変更されない入力に問題ありません。これらは読み取り専用マウントのままにすることができます。認証情報ファイルはマウントまたはストリーミングされません。エージェントコンテナは認証情報を保持しないためです(認証情報プロキシを参照)。実行中に変更されるファイルは、オーケストレーターによってdocker execを通じてコンテナに書き込まれ、最新の状態に保たれる必要があります。コンテナ内のコピーは、エージェントが編集できる通常のファイルであるため、オーケストレーターにホスト上のオリジナルを読み取らせ、テスト中のエージェントが到達できないコピーから調査結果を判断してください。

各エージェントはそのネットワーク用のコンパニオンコンテナが必要です

マイクロVMのネットワークインターフェイスはVMがブートするときに存在する必要があります。Firecracker は後で追加することはできません。ただし、Docker はランタイムがコンテナを作成した後にのみコンテナのネットワークを接続します。リファレンス設計はこれを回避します。最初に、正しいネットワークに接続され、sleepのみを実行する小さなアイドルコンテナを起動し、次にそのコンテナのネットワークネームスペース内でエージェントを起動します(--network container:<name>)。Kataはそこでインターフェイスを見つけてVMに接続します。コンパニオンは正確に1つのVMに対応します。Kataはそれをそこに残すため、ペアを一緒に作成および削除し、コンパニオンを再利用しないでください。1つは約12 MBのアイドルプロセスのコストがかかります。

スタックしたエージェントを停止する

docker rm -f <agent-container>で十分です。オーケストレーターは死んだコンテナを検出し、実行を失敗としてマークし、実行を破棄するときにコンパニオンコンテナを削除する必要があります。

すべてはIPでアドレス指定されます

Dockerの組み込みDNSはホスト側のネットワークネームスペースで実行され、ゲスト内からはアクセスできないため、プロキシをIPアドレスとしてエージェントに渡し、ネットワーク対象に静的IPを割り当ててください。

docker execは機能しますが、docker cpは機能しません

docker execをエージェントコンテナに実行すると通常通り動作します。ゲスト内のKataのエージェントがコマンドを実行します。docker cpをエージェントコンテナに対して実行または実行元にすることはできません。コンテナのファイルがゲスト内の仮想ディスク上にあるためです。docker exec <container> cat <path>などを使用してください。

Firecrackerはそのジェイル内でrootとして実行されます

Kataはuid 0でジェイラーを起動するため、Firecrackerプロセスはchroot、ネームスペース、seccompフィルター、およびcgroupによって制限されており、非特権ユーザーIDではありません。すべてのVMが共有する2つのファイル(ゲストカーネルとイメージ)は、代わりに不変フラグによって保護されています(Kataの設定を参照)。

Kataはfirecrackerが依存するランタイムを廃止しました

KataはFirecrackerを古いGoランタイムで実行します。Kata 4.0は他のハイパーバイザー向けの新しいRustランタイムをデフォルトにし、Goランタイムを廃止しました。アップストリームによると、Goランタイムは引き続き重大なバグ修正とCVE修正を受け取っており、Kata 5.0以前には削除されない可能性があります。Rustランタイムはハイパーバイザーの中にFirecrackerをリストしておらず、アップストリームはDocker統合を主にQEMUでテストしています。移行を計画してください。Kataバージョンを変更する場合は、新しいホストの検証を繰り返してください。KataはFirecrackerの代わりにCloud Hypervisorを使用することもできます。リファレンス実装はその構成をテストまたは強化していません。

ログ

Kataのランタイム、Firecracker、およびゲストエージェントのメッセージはジャーナルに送信されます:journalctl -t kata。containerdおよびDockerの問題はjournalctl -u containerdおよびjournalctl -u dockerにあります。

こちらの回答で解決しましたか?