空き領域は空ではなかった
9 月 24 日、Cloudflare と Accomplish の Oren Yomtov が、Cloudflare Containers と Sandboxes におけるテナント間の欠陥を公開した。新しいサンドボックスに 4 KiB 書き込み、生のディスクを読む。すると同じブロックの残り 60 KiB が、前のテナントの .env ファイル、認証情報ファイル、Chromium プロファイルを抱えたまま返ってくる。何も何かから脱出したわけではない。動いている境界はすべて持ちこたえ、漏れは、所有者が使い終わったあとにブロックがどう扱われるかの中にあった。Cloudflare は言語モデルが生成したコードを動かすために Sandboxes を売っている。Bromure Agentic Coding はそのコードをあなた自身の Mac 上のイメージファイルから動かし、そこが引き出す空きブロックはあなたのものだ。
サンドボックスの仕事は二つある。中で動くものを閉じ込めること、そして以前に中で 動いていたものを忘れること。二つめは設定オプションである。
あなたはエージェントのテストスイートをクラウドのサンドボックスへ送る。レビューし
ていないコードを自分のラップトップで走らせるのが賢く思えなくなったのは、去年の
どこかだった。サンドボックスは 1 秒ほどで、完全な Linux ファイルシステムとともに
立ち上がる。エージェントは小さなファイルを書く。その下で、プラットフォームは
64 キロバイトのディスクブロックを手渡し、そのうち 60 キロバイトには、まだ他人の
.env が入っている。
そこへ至るために、あなたは何かから脱出する必要はなかった。
4 キロバイト書いて、60 キロバイト読む
9 月 24 日、Cloudflare は Cloudflare Containers におけるテナント間の欠陥について 研究者との共同レポートを公開した。 Accomplish の Oren Yomtov は 9 月 4 日に HackerOne 経由で報告し、同じ週に 自身の記録も公開した。 The Hacker News はその翌日に報じた。
Containers は、Linux の device-mapper シンプロビジョニングを使い、共有プールから
各顧客にディスクを割り当てる。ブロックサイズは 64 KiB。そのプールには
skip_block_zeroing オプションが付いていた。名前の通りの動作をするもので、
dm-thin は新しく割り当てたブロックをコンテナに渡す前に消去しなかった。コンテナが
削除されると、そのブロックは内容をそのままにしてプールへ戻り、プールは顧客
アカウントをまたいでいた。
そこから先の手口は 4 ステップ、エクスプロイトはゼロである。
- コンテナ自身の ext4 ファイルシステムが空きと考えている、64 KiB 境界に揃った 領域を見つける。
- そのそれぞれに 4 KiB ブロックを一つだけ書く。それだけで dm-thin は共有プール から物理 64 KiB ブロックを割り当てる。
- ファイルシステムではなく生のデバイスを読む。
- 残りの 60 KiB を手元に置く。
このプリミティブを言い表した Cloudflare 自身の一文が、そのままバグの全体である。 「ブロック全体を覆う書き込みは以前の内容を置き換えたが、より小さい書き込みは書か れた部分だけを変えた。」
回収されたブロックには、使える構造が残っていた。Cloudflare は「ディレクトリ構造、
データベースページ、そして構造的に完全な SQLite データベース」を報告し、6 つの本番
配置先にわたって異なる他人のディレクトリ inode を 2,700 個数えている。24 の配置
先のうち 18 に残留物があった。The Hacker News は、4 大陸にまたがる 22 台の基盤マシ
ンのうち 20 台でデータが回収されたと報じている。Yomtov はそれらのブロックから読み
取ったものを挙げている。「ディレクトリ一覧、SQLite データベース、Chromium プロファ
イル、.env ファイル、認証情報ファイル。」
Cloudflare はこのインシデントを囲う二つの限界を述べている。攻撃者は「特定の被害者 を選ぶことも、能動的に接続されているディスクにアクセスすることもできなかった」。 つまり手に入るのは、そのマシンに居合わせた誰かであって、選んだ標的ではない。そして Cloudflare は研究者の実証コードから検知シグネチャを作り、過去のディスク活動テレメ トリに対して走らせ、「この特定の攻撃ベクタが他の誰かに悪用された証拠は見つからな かった」としている。
Cloudflare の動きは速かった。9 月 4 日 15:26 UTC に報告。18:45 に本番の設定ミスを 確認。21:27 にランタイム修正をマージ。22:03 にプール設定をマージ。23:15 にロール アウト開始。すべてが 1 日のうちである。ロールアウトは 9 月 7 日に完了し、研究者は 9 月 14 日に実証コードが死んだことを確認し、Cloudflare は 9 月 19 日に緩和前の ディスクスナップショットの最後の分を消した。顧客側に取るべき行動はなく、自分の ブロックがきれいな状態で届いたのかをサンドボックスの中から確かめる方法もなかった。
動いている境界はすべて持ちこたえた
Yomtov のレポートの題、「Escaping the Cloudflare Sandbox」は、このバグがどれほど 静かなものかを言い足りていない。
彼が見つけたのは、メモリ安全性のバグでも、権限昇格でも、コンテナの脱出でもない。 動作中のコンテナを取り巻く境界は、インシデントの全期間にわたって設計どおりに 持ちこたえた。顧客 B は顧客 A の生きているコンテナを読めなかったし、Cloudflare は サンドボックスが能動的に接続されたディスクにも届かなかったと述べている。
漏れは引き継ぎの部分に座っていた。Cloudflare はあるテナントからブロックを解放し、 それを次のテナントへ発行した。そして二人の顧客の間に立っていたものは、プール設定の 中の真偽値一つだった。
研究者は、サンドボックスの中のコードがいま何に手を伸ばせるかに注意を注ぎ、最後の 住人が何を残していったかにはずっと少なく注ぐ。後者の問いには、たいていつまらない 答えがある。プラットフォームがブロックをゼロ化する、というものだ。その答えは、 あるエンジニアがスループットのためにゼロ化を切るまで保たれる。
Accomplish はこれを、2026 年 7 月以降に公開した 6 件目のサンドボックス脱出として 数えている。前の 5 件は、Claude Cowork の SharedRoot、Claude Code の Beltdown、Cursor の CLI の Beltdown2、Docker の VMM のもの、そして OpenAI の Codex サンドボックスのもの。この 6 件のうち 5 件は、エージェントが書いたコードを 実行する場所である。Yomtov 自身の結論は一行だ。「分離は多くの仕方で失敗しうる。」
エージェントのコードは、まさにそこへ行くはずだった
Cloudflare Sandboxes は Containers の上で動くので、このバグを引き継いだ。Sandboxes はまた、このブログが書き続けているまさにその用途のために Cloudflare が売っている 製品でもある。Cloudflare 自身のドキュメント によれば、この SDK は「信頼できないコードを隔離された環境で安全に実行する」ために 存在し、「大規模言語モデルが生成したコードを安全かつ確実に実行する」ためのもので、 「信頼できないコードを実行する必要がある AI エージェント、コードアシスタント、自律 システム」に向いている。各サンドボックスは「完全な Linux 環境を備えた独自の隔離 コンテナの中で動作し、性能を保ちながら強固なセキュリティ境界を提供する」。
この一つ一つの文言は、望んで当然のことだ。そしてそれは、Cloudflare Sandbox を説明 するのと同じくらいよく Bromure のワークスペース VM も説明する。違いは、そのマシンに 他に誰がいるかである。
エージェントの実行をラップトップの外へ移すことは、信頼の判断をなくすのではなく、 置き場所を変えるだけだ。あなたはこれから、見ることのできないプールアロケータを、 自分が選んでいない配置先で、誰も名前を教えてくれないテナントの隣で信頼することに なる。それが正しい取引であることもある。意図してそうすること、そしてまず残留物に ついて問うこと。自分の空きブロックはどこから来るのか、そこには何が入っていたのか。
ディスクはあなたの Mac 上のファイルである
Bromure Agentic Coding はこの問いに、プールを持たないことで答える。
ワークスペースはちょうど一つの VM に対応する。二つのワークスペースが VM を共有する
ことはなく、一つのワークスペースが二つ持つこともない。VM は二つの仮想ディスクから
起動し、それらはあなたの Mac 上の、そのワークスペース専用のディレクトリにある普通
のファイルである。disk.img はシステムディスクで、初回起動時にローカルの Ubuntu
ベースイメージの APFS コピーオンライトクローンとして作られる。即時に、そしてゲストが
書き込むまで無償で。home.img は /home/ubuntu を保持する専用のスパース ext4
イメージで、二つめの virtio-blk デバイスとして接続される。
4 ステップの手口は、ここでは着地する場所がない。ゲストの中のエージェントはファイル システムではなく生のブロックデバイスを読める。中では root だからで、それは問題ない。 届くのは、一つのワークスペースに属する一つのイメージファイルである。そのファイルが 育って入っていくブロックは、あなた自身の Mac の APFS ボリュームから来る。そして あなたの Mac 上の空きブロックの前の住人は、あなただった。
ワークスペース間で共有されている対象が一つある。「何も共有していない」は誤った主張
になるので、名前を挙げておく。すべてのワークスペースのディスクは base.img から
クローンされる。Ubuntu 24.04、論理 24 GB、物理 6 〜 8 GB。署名付きイメージカタログ
に対して取得され、そのカタログはアプリの更新に署名するのと同じ鍵で作られた ed25519
署名を持ち、イメージの同一性、その SHA-256、そしてすべての postinstall コマンドを
覆っている。ロールバック保護があり、署名のないカタログは拒否される。どのインストール
でもバイト単位で同一で、あなたのものは何も含まない。それは共有してよい種類のもの
である。どこでも同一であることが仕事の、公開された成果物だ。
そして残留物には価値がない
ブロックの配置は答えの半分である。もう半分は、コーディングエージェントがディスクに
何を書くかだ。そしてそれこそが、このバグを報告に値するものにした。.env ファイル、
認証情報ファイル、Chromium プロファイル。
Bromure のワークスペースの中では、それらのファイルは存在し、それを読むツールも普段
どおり動く。ただし中の値は偽物だ。VM の中のファイル、環境変数、プロセスのいずれも、
本物の API キー、OAuth トークン、AWS シークレット、SSH 秘密鍵を持つことはない。
ゲストが受け取るのは、構造を保ったプレースホルダである。sk-ant-api03-brm-…、
ghp_ の形をした GitHub トークン、brm_…。インストールごとに決定的なので、
クライアント側のバリデータは満足し、鍵がセッション間でローテートされたと考える
ツールも出てこない。本物の値は Mac 上のホストプロキシのメモリ内スワップマップに住み、
それぞれが属する宛先ホストに紐づけられ、送出時に差し替えられる。そのスコープは
完全一致かサブドメインで、部分文字列では決してない。AWS リクエストはホスト側で
再署名される。ゲストは偽のシークレットで署名し、ホストはその署名を取り除いて署名し
直す。SSH は vsock ブリッジ越しの署名のみで、秘密鍵のバイト列がゲストへ渡ることは
まったくない。
Chromium プロファイルについては、Bromure は別扱いにする。エージェントが操作する ブラウザペインは、それ自身の一時的な Alpine VM の中で動く。一時ディレクトリの中の コピーオンライトクローンで、ペインを片付けるとアプリがそれを削除する。ログインを 保持するのはオプトインで、その場合はプロファイルをワークスペースごとの暗号化 ディスクに置く。
将来なんらかの欠陥が Bromure のゲストのブロックを露出させたとしても、読み手が持ち 帰るのはディレクトリツリー、あなたがすでに持っているソースコード、そしてどこでも 使えない認証情報ファイルである。
使い捨てを動詞として
ワークスペースは意図して永続的である。コーディングには持続する状態が必要だ。クローン したリポジトリ、パッケージキャッシュ、ツールチェーン、シェル履歴。だから Bromure は、 VM を毎晩壊すのではなく、VM が何を保持してよいかを制御する。そしてディスクを消す のは、あなたが頼む行為である。アプリは、その頼み方のそれぞれについてはっきり言う。
ベースへリセット
disk.img を削除し、次の起動でベースイメージの新しいコピーを再クローンさせる。
ダイアログは消えるものを名指しする。apt install したものすべて、そして
/etc、/var、/usr、/opt へのあなたの変更。home は残る。
home を消す、ワークスペースを削除する
home を消すと /home/ubuntu と生成された鍵ペアが落ちる。ワークスペースを削除
すると、プロファイルディレクトリ全体、両方のイメージ、暗号化されたシークレット
ファイル、すべてのチェックポイント、ホスト側の SSH 素材が取り除かれ、そのあと
予約された MAC アドレスが解放される。
使い捨てとチェックポイント
bromure-cli vm run --rm は、VM が止まったら削除される docker 風のワークスペース
をくれる。起動が成功するたびに、ディスクと home のコピーオンライトチェック
ポイントが残る。動くターミナルを生んだ起動のあとにのみ取られるので、どれも起動
できることが確かめられている。
強制ワイプ
プレースホルダの認証情報が、属していない先へ向かうのをプロキシが捕らえると、 Bromure はそのワークスペースを侵害済みと印し、ディスクと home をワイプするまで 二度と起動しない。設定、トークン、SSH 鍵は保たれ、ワイプが共有ホストフォルダに 触ることはない。
この動詞の一式が、あなたが頼んだ消去と、あなたが前提しただけの消去との違いである。
前の借り手が何を残したかを問う
Cloudflare は設定ミスを見つけ、9 時間で直し、プールとスナップショットを片付け、 過去を確かめるための検知シグネチャを作り、ブロックサイズとフラグの名前を公開した。 これは、悪い一日をうまく扱ったベンダーとして読める。
「サンドボックス」は境界についての希望に名前を付けた言葉であり、この境界は壁ではなく リソースのライフサイクルだったと判明した。レビューしていないコードを実行する エージェントに対する業界の答えは、実行をどこか別の場所へ移し、その別の場所がきれいな 状態で届くと信じることだった。たいていは届く。それをサンドボックスの中から確かめる ことは、今週もどの週もできない。
自分が見ることのできるインフラでコードを動かせば、残留物についての問いに自分で答える ことになる。ワークスペースごとに一つのイメージファイル、自分自身のボリュームから来る 空きブロック、共有されている対象は一つだけでそれは署名済みの公開ベースイメージ、 そしてもし漏れたとしてもそのディスクには読む価値のあるものが何もない。それを消すのは メニュー項目である。