「サンドボックスで動かして」というのは 1 つの指示のように聞こえます。実際には、人がこの言葉で指す一般的な境界は 4 つあり、止められるものはまったく違います。間違ったものを選ぶと、無防備なままになるか、毎回の実行が必要以上に遅く高くなります。
この比較では、コードが本当に信頼できないものだと仮定します。言語モデルが書いたもの、ユーザーが投稿したもの、見知らぬ人の pull request で届いたものです。自分で書いたコードには別のニーズがあります。
何が起こりうるか
境界を比べる前に、それが何のためにあるのかをはっきりさせておくと役に立ちます。信頼できないコードは、次のようなことをする可能性があります。
- 読むべきでないものを読む: 環境変数、SSH キー、ホームディレクトリのファイル、クラウドのメタデータエンドポイント。
- リソースを使い果たす: 無限ループ、マシンが固まるまでの fork、ディスクを埋め尽くす。
- ネットワークを悪用する: ほかのホストのスキャン、スパム送信、暗号資産のマイニング、社内サービスの呼び出し。
- 居座る: タスクより長く生き残る cron ジョブやサービスを仕込む。
- 抜け出す: 下の層のバグを使ってホストそのものでコードを実行する。
以下の各レベルは、このうちのいくつかに対処し、ほかには対処しません。
レベル 1:プロセス
最も単純なサンドボックスは子プロセスです。タイムアウト付きの subprocess.run、場合によっては別ユーザーで、念入りならリソース制限と seccomp フィルターも付けます。
防げるもの: 時間の暴走(タイムアウト)、一部のリソース枯渇(制限)、一部の危険なシステムコール(seccomp)。 防げないもの: そのユーザーが読めるものすべての読み取り、ネットワークアクセス、そのユーザーが書き込める場所を使った居座り、そしてあらゆるカーネルのバグ。 典型的な破られ方: 読めることを忘れていたファイルをコードが読む、あるいは「制限付き」の言語インタープリターに抜け穴があったと判明する。言語内サンドボックスが破られた例は歴史上いくらでもあります。
起動時間は実質ゼロです。自分で書いたコードなら問題ありませんが、他人が書いたコードに対しては境界になりません。
レベル 2:コンテナ
namespaces はコードにファイル、プロセス、ネットワークの独自のビューを与え、cgroups は CPU とメモリを制限し、削られた capabilities と seccomp はカーネルに要求できることを狭めます。
防げるもの: ホストのファイルの読み取り(マウントされていない限り)、ほかのプロセスの閲覧、無制限のリソース使用、そしてコンテナを使い捨てにするなら居座り問題の大部分。 防げないもの: 共有しているホストカーネルのバグ。マシン上のすべてのコンテナが同じカーネルと話しているので、到達可能なカーネルの脆弱性は出口になります。 典型的な破られ方: 珍しいエクスプロイトではなく設定です。特権コンテナ、中にマウントされたコンテナランタイムのソケット、「デバッグのためだけ」に有効にしたホストネットワーク。どれも静かに境界を取り払います。
起動時間はミリ秒です。システムコールがホストに届く前に横取りするユーザー空間カーネルなど、速度や互換性と引き換えに強化した方式もあります。信頼できる人のコードなら、きちんと設定したコンテナは妥当な既定の選択肢です。
レベル 3:microVM
microVM は完全な VM と同じようにハイパーバイザーの下で独自のカーネルを動かしますが、エミュレートするハードウェアをほぼすべて取り除いています。Firecracker が最もよく知られた例です。
防げるもの: コンテナが防げるものすべてに加えて、カーネル共有の問題。ホストに到達するには、ハイパーバイザーか少数の仮想デバイスのいずれかを破らなければならず、その攻撃面はカーネルのシステムコールインターフェースよりはるかに小さいものです。 防げないもの: 渡したものの悪用。開放された送信通信は依然として悪用されえますし、注入した秘密情報は依然として漏れえます。 典型的な破られ方: 隔離ではなくポリシーです。誰かが「テストを通すために」本番のトークンを渡したり、送信通信が不要なワークロードでそれを無制限のままにしたりします。
起動時間は 1 秒足らずから約 1 秒で、オーバーヘッドは数メガバイトです。タスクごとに作って終わったら削除できる速さで、これは居座りの問題も解決します。戻ってくる先が何も残らないからです。
レベル 4:完全な仮想マシン
通常の VM、あるいは VPS は、microVM と同じ種類の境界、つまりハードウェア仮想化とハイパーバイザーを持っています。違いはその周りのすべてです。完全なデバイスモデル、OS 全体、望めば公開 IP、そして日や月の単位で測るライフサイクル。
防げるもの: microVM と同じ種類の問題。ただしエミュレートするハードウェアが多いぶん、攻撃面はやや大きくなります。 防げないもの: 自身のネットワーク上の身元の悪用。公開 IP を持つ VM で悪質なコードを動かすと、その VM 自身の IP がブロックリストに載ります。その IP であなたのメールも送っているなら大問題です。(すでにそうなってしまったなら、IP がブロックリストに載ったときの対処法を参照してください。) 典型的な破られ方: 長生きしすぎることです。1 つの実験のために作った VM が認証情報や状態をため込み、守るはずだった信頼済みのマシンへと少しずつ変わっていきます。
起動時間は数十秒から数分で、課金はたいてい月単位です。受信ポートを必要とする長時間稼働のサービスには合った形で、20 秒のコード実行には合わない形です。
比較
| プロセス | コンテナ | microVM | 完全な VM | |
|---|---|---|---|---|
| 独自のカーネル | なし | なし | あり | あり |
| 主な境界 | ユーザー権限 | namespaces + 共有カーネル | ハイパーバイザー、極小のデバイスモデル | ハイパーバイザー、完全なデバイスモデル |
| 起動時間 | 約 0 | ms | 約 0.1〜1 秒 | 10 秒〜数分 |
| オーバーヘッド | なし | 小 | 数 MiB | 数十〜数百 MiB |
| タスクごとの使い捨て | 簡単 | 簡単 | 簡単 | 遅く、高コスト |
| 受信ポート / 公開 IP | ホストのもの | ホストのもの | 通常なし | あり |
選び方
- 自分やチームが書いたコード: プロセスかコンテナで十分です。
- 自分のブランチの CI: 自分の runner 上のコンテナ。
- エージェントが生成したコード、ユーザーの投稿、外部の pull request: タスクごとに microVM を 1 つ作り、終わったら削除。
- 接続を受け付ける必要がある、あるいは何週間も動く信頼できないサービス: 独自の IP を持つ別の VM。認証情報を持つものやメールを送るものからは遠ざけます。
何を選んでも、さらに 2 つのルールが当てはまります。コードの作者に渡したくないものは中に置かないこと、そしてネットワークに何を許すかを意識して決めることです。
私たちの製品の位置づけ
レベル 3 にはコードサンドボックスを提供しています。約 1 秒で起動する Firecracker microVM で、インターネットへの送信が可能、受信ポートはなく、秒単位で課金されます。まさに上の 3 つ目の項目のためのものです。エージェントがそれで何をできるかを制限する方法は MCP のガードレールのページで説明しています。レベル 4 には、AI agent プランのような VPS が月単位でマシン 1 台を丸ごと提供します。AI エージェント向けサンドボックスの実例では microVM のパターンを最初から最後まで紹介しており、AI エージェントがインフラに求めるものでは隔離を複数の要件のひとつとして取り上げています。
コメント
まだコメントはありません。最初になりましょう。