すべての投稿に戻る
公開日 · 著者 Renaud Deraison

トークンは隣のプロセスから漏れた

研究者たちは、サンドボックスからの脱出もメモリ安全性のバグもなしに、隣り合った Cloudflare Worker から JWT を毎秒 12 ビットで引き出した。アイソレートの境界は破られていない。それでも秘密は境界を越えた、下にあるハードウェアを通って。いまクラウドのプラットフォームは、AI エージェントが書いたコードを走らせる場所として、まさにその境界を提供している。Bromure Agentic Coding はもう一層下に線を引き、そもそも資格情報を箱の中に置かない。

あるテナントの JavaScript が、CPU に対して形を整えた質問を数百万回投げ、その答え の中から別のテナントの認証トークンを読み取った。プラットフォームが引いた境界の内 側に留まったまま、ふつうの JavaScript として走り、そのあいだ境界はずっと役目を果 たしていた。

8月17日、研究者チームが Remote-Timer-as-a-Service を公開し、19日には Cloudflare が この研究についての自社の説明 を出した。彼らは JSON Web Token、つまりサービスがあなたの身元の証明として受け取る 署名済み文字列を、本番環境で同居する Cloudflare Worker から、最大で毎秒 12 ビット、 精度 99.16% で引き出した。同じプラットフォームに対する以前の公開成果は 2021 年のも ので、毎分 2 ビットだった。360 倍の速度になると、それは物珍しさではなく盗まれた資 格情報になる。

Cloudflare はすでに修正し、3 年間ほかの誰かがこれを使った形跡はないとし、顧客デー タへのアクセスはなかったと述べている。その先を読んで、この攻撃が一度もやらずに済ま せたことを見てほしい。

何ひとつ壊す必要がなかった

Cloudflare Workers は少ないハードウェアで多数のテナントを走らせており、それを可能に しているのは、ふだん彼らを隔てているものを省く点にある。Cloudflare 自身の言葉では、 Workers は「複数テナントのコードを、同一のオペレーティングシステムプロセス内の別々 の V8 アイソレートで実行する」。アイソレートとは JavaScript レベルのコンテナだ。自 前のヒープ、自前のグローバル、共有メモリなし、スレッドなし。数ミリ秒で起動する、と いうのが要点そのもので、プロセス分離はリクエストごとにコールドスタートの代償を払わ せるからだ。

攻撃者に必要なのは、あるアイソレートの中で走るコードだ。被害者を同じプロセスへ引き 込む部分が巧妙だ。攻撃者の Worker が被害者を呼ぶのである。研究者が書いているとおり、 攻撃者のスクリプトから fetch("https://victim.example") で被害者を呼び出すと「多く の場合、スケジューラは被害者ワーカーのインスタンスをまさに同じプロセス内で立ち上げ る」。同居を待つのではなく、呼び寄せるのだ。

そこから先は Spectre だ。分岐予測器を誤学習させ、CPU が本来決して行わないはずの読み 取りを投機的に実行するように仕向け、次にキャッシュを測って何を読んだかを知る。 Cloudflare はそれを難しくするのに何年も費やしてきた。SharedArrayBuffer なし、スレ ッドなし、キャッシュヒットほど小さなものは測れないよう凍結され粗くされたタイマー、 そしてハードウェア性能カウンタを監視し、Spectre の匂いがするものを自分専用のプロセ スへ移す Dynamic Process Isolation(DyPrIs)だ。

研究者たちはその一つひとつを迂回した。

時計は外から来た。Durable Object への、あるいはインターネット上のありふれたタイムス タンプサーバへの WebSocket が、時計を渡すことを拒むプラットフォームの内側にサブミリ 秒の分解能をもたらす。そのうえで彼らは、信号を分解するのではなく増幅した。L1 キャッ シュの tree-PLRU 置換ポリシーは二分木のポインタをたどるので、一度のキャッシュ事象を 長いヒットの連なり、あるいは長いミスの連なりへ変えられる。「単一のキャッシュ事象の タイミングは任意に増幅できる」と彼らは書く。測る対象を巨大にしてしまえば、ぼやけた 時計でかまわない。

DyPrIs は二重に取り逃がした。スクリプトを隔離するのは呼び出しが終わったあとであ り、キープアライブのメッセージで生かされ続ける Durable Object は数時間、最長で丸一日 走るので、エクスプロイトは終わらない単一の呼び出しの内側で完了する。さらに分岐予測 ミスを iTLB アクセスで正規化するのだが、Cloudflare の言葉では「我々のリモートタイマ ーは一つの大きな I/O ループであり、その WebSocket トラフィックが iTLB の活動を膨らま せる」。研究者たちは、警報が正常を示すまで自分たちの分母を育てたのだ。

残りは配管仕事だ。アイソレートのルートアドレスを漏らす投機的型混同ガジェット、それ を任意読み取りに変えるための typed array のバッキングストアに対する 64 ビットポイン タ混同、そして被害者の JWT を 1 ビットずつ。

1 つの OS プロセス。2 つのテナント。JavaScript でできた境界。OS プロセス攻撃者アイソレートfetch("https://victim.example")被害者をこのプロセスへ呼び込むふつうの JavaScript、ネイティブなし被害者アイソレート自前のヒープ、自前のグローバル共有メモリなし、スレッドなしJWT はそのアドレス空間に外から来る時計タイムスタンプ用 WebSocketサブミリ秒の分解能プラットフォームのタイマーは凍結のまま共有 CPU:分岐予測器、L1 キャッシュ、tree-PLRU 置換アイソレートの境界はここには存在しない — 一度のキャッシュ事象が、ぼやけた時計でも読める長さの連なりへ増幅される結果:被害者の JWT を 1 ビットずつ — 最大 12 bit/s、精度 99.16%、2021 年の 360×
攻撃者は自分のアイソレートから一度も出ない。スケジューラが同じプロセスに置くように被害者を呼び出し、プラットフォームの外にある WebSocket から時計を借り、一度のキャッシュ事象を測定できる長さの連なりへ増幅し、両方のアイソレートが共有するハードウェアを通じて隣人のトークンを 1 ビットずつ読む。

修正のほうが発見より多くを語る

Cloudflare は三つの緩和策を投入した。まとめて読んでほしい。

彼らは V8 Sandbox を統合した。これは JavaScript ヒープ領域から生の 64 ビットポイ ンタを取り除き、typed array のガジェットを殺す。DyPrIs には、長寿命の Durable Object と I/O 中心のワークロードをノイズではなく一級のセキュリティ事案として扱うよう 教えた。そして Memory Protection Keys を配備し、共有プロセスの内側で各テナントの ヒープをハードウェアで強制されるアクセス境界の後ろに置いた。

三つとも JavaScript のセマンティクスより硬いものを求めて JavaScript の下へ降りてお り、三つめは CPU そのものに着地している。Cloudflare は V8 Sandbox が「完全な Spectre 緩和策ではない」と率直に述べている。言語レベルの境界をハードウェアレベルの境界を足 すことで直す技術者たちは、本当の線がどこにあると考えているかをすでに語っている。

エージェンティックコーディングのブログが、CDN について書く

アイソレートは CDN を離れた。3 月、Cloudflare は Sandboxing AI agents, 100x faster という題で Dynamic Workers を出した。1 秒前には存在しなかったコードで、実行時に Worker を立ち上げる仕組みだ。自分でスクリプトを書いて実行するエージェントを走らせた ことがあるなら、その動機はわかる。「エージェント(あるいは MCP サーバ)が、タスクを こなすために AI がその場で生成したコードを実行するのなら、そのコードはどこかで走らな ければならない」、そして「AI が生成したコードを自分のアプリの中で直接 eval() する わけにはいかない」。

Cloudflare は同じ記事で仕組みの名前を挙げている。「Dynamic Workers は、Cloudflare Workers プラットフォーム全体が 8 年前のローンチ以来ずっと築かれてきたのと同じ基盤の サンドボックス機構、すなわちアイソレートを使う。」理由は速度だ。アイソレートは数メガ バイトで数ミリ秒で起動し、コンテナよりおよそ 100 倍速く、メモリ効率は 10 倍から 100 倍よい。だからリクエストごとに新しいサンドボックスを用意することが、使い回すたびに 弱っていく生ぬるいプールの代わりに、現実的な選択肢になる。

Cloudflare は代償についても率直だ。自社のベータ記事は八つの単語で言い切っている。 「V8 のセキュリティバグはハイパーバイザの脆弱性より一般的だ。」 誰かがトークンを 漏らすより何か月も前に、彼らはそう書いていた。

つまりここにある物語は取引であり、それを行う当人たちが書き残し、いまや研究者によって 毎秒 12 ビットという値段がついた。問いはほかのみんなの側に落ちてくる。サンドボックス に入れられるコードがモデルによって書かれ、パッケージやウェブページが吹き込んだ内容に 形作られ、ベアラートークンの隣で走り続けるとき、それはあなたが望む取引だろうか。

Bromure はハイパーバイザに線を引く

Bromure Agentic Coding は、他人のコードの隣で言語レベルのコンテナの中にあなたのエー ジェントを置いたりしない。ワークスペースはそれぞれ、Apple の Virtualization.framework 上の Linux 仮想マシンであり、Apple Silicon 専用だ。自前のカ ーネル、自前のゲストメモリ、読み取り専用のベースイメージから複製された自前のディスク を持つ。プロセスを共有しないということは、呼び寄せられる同居テナントが存在しないとい うことであり、あなたのエージェントが走る境界はハイパーバイザ、すなわち Cloudflare 自 身の比較でバグがより稀とされた側だ。

これがアーキテクチャの話だ。今回の攻撃を無意味にしたであろうものはもっと狭く、もう一 歩内側にある。

トークンは最初から箱の中になかった

研究者が持ち帰ったのは、被害者のアドレス空間にあった JWT、つまり動いているサービスが 自分の使う資格情報を置いておく場所にあったものだ。シェルも root も取っていない。

Bromure のワークスペースは、そこに資格情報を置かない。

プロファイル内のあらゆるシークレットはあなたの Mac に留まる。ANTHROPIC_API_KEY、 GitHub のパーソナルアクセストークン、AWS のアクセスキー、kubeconfig のベアラートーク ン、コンテナレジストリの Basic 認証の blob、Linear のキーがそれに含まれる。Bromure が VM に注入するのは偽物だ。brm_… というプレースホルダ、使い捨てのクライアント証明 書、派生させた Basic 文字列。エージェントはそれを読み、SDK もそれを読み、gitkubectldoctl もそれを読む。それでも仕事は通る。ホスト側の MITM プロキシが送 信リクエストで本物の値に差し替えるからだ。AWS にはもう一段ねじが締められている。ホ ストは本物の材料で SigV4 リクエストに署名し直すので、プロキシを回避したものは、動く 呼び出しではなく Amazon からの InvalidSignatureException を受け取る。

だから、その VM の中で完璧な任意読み取りを手にした攻撃者は、研究者が論文を一本かけて 組み上げたあのプリミティブをもってしても、おとりを読むことになる。バイトはそこにあ り、パースもでき、鍵のように見え、そしてマシンの外では何も買えない。分離の境界が完璧 かどうかにかかわらずそうなる。ワークスペースには盗む価値のあるものが空だからだ。

従来型:境界はソフトウェアで、秘密はその内側にあるアイソレート内のエージェント他のテナントと OS プロセスを共有本物のトークンがアドレス空間に下にある共有ハードウェアキャッシュと分岐予測器境界が止めたビットを運ぶ隣人トークンを読む12 bit/s、99.16%BROMURE:境界はハイパーバイザで、秘密はその向こう側にあるワークスペースの VM自前のカーネルとメモリ、同居テナントなしANTHROPIC_API_KEY=brm_…偽物 — 任意読み取りはおとりを読むMITM プロキシ、ホスト側偽物を本物の値に差し替える送信先は egress ルールが決める利用ごとの承認ダイアログ(任意)本物の API本物の資格情報を受け取る。送信はあなたの Mac から差し替えのすべて、許可・拒否されたすべての接続:Window → Security Timeline の 1 行として、VM の外に書かれる
従来、隣人とあなたの資格情報のあいだにあるのはサンドボックスの境界だけで、資格情報はサンドボックスの内側にある。Bromure のワークスペースでは境界はハイパーバイザであり、資格情報はその向こう側にある。ゲストが持つのは偽物で、ゲストが到達できないプロキシが通信路上で本物の値に差し替える。

毎秒 12 ビットにも、出ていく先が要る

サイドチャネルは持ち出しの半分でしかない。もう半分は外へ出る経路であり、毎秒 12 ビッ トというのは、しばらく開いたままにしておかねばならない経路だ。400 文字のトークンなら、 攻撃者が支配する宛先へ何分もトラフィックを流すことになる。

Bromure のプロファイルは、短い pf 風のポリシーとして書かれ、テーブルとして編集される 独自の egress ルールを持つ。それを強制するのはあなたの Mac であり、仮想スイッチとプロ キシの中でのことだ。ゲストの内側にあるものには発言権がない。拒否された接続には reset が返り、その判断はホスト、IP、ポート、判定を伴う egress.firewall の行として Window → Security Timeline に残る。ワークスペースで走るコードは、自分が変えたいと 思うルールの、間違った側にいる。

本物の資格情報を使うそのつど、手を添えることもできる。シークレットごとに Require approval to use をオンにすればよい。モデルの API キー、SSH 署名、GitHub と GitLab と Bitbucket のトークン、kubeconfig の各コンテキスト、DigitalOcean、AWS SigV4 の署名一つ ひとつ、各コンテナレジストリ、そしてあなたが追加した手動のトークンルール。差し替えは そこで止まり、macOS 上のダイアログを待つ。あなたは 5 分、1 時間、あるいはセッション単 位で許可する。ゲストがその問いに答える機会は決してない。

取引こそが物語だ

アイソレートは優れた工学であり、Cloudflare の対応は望ましいものだった。協調的な開示、 三つの実質的な緩和策、V8 Sandbox が何をカバーし何をカバーしないかについてのごまかしの なさ。毎秒数百万のリクエストがコンテナの上で走っていないのには理由がある。

CDN では議論に勝ったのはコールドスタートだ。だが、あなたのコーディングエージェントは 4 ミリ秒で HTTP リクエストに応答しているわけではない。1 時間走り、誰も監査していないパ ッケージを入れ、モデルが書いたテストスイートを実行し、ひとこと言いたそうなウェブページ を読む。そのワークロードを走らせるものは何であれ、そのあいだずっとあなたのトークンを抱 えている。そして実行されるコードについてあなたが知っている唯一のことは、それを書いたの があなたではない、ということだ。

その仕事にとって、VM 起動の数百ミリ秒は削るに値するコストではない。Cloudflare はすでに 為替レートを公表している。V8 のバグはハイパーバイザのバグより一般的だ、と。Bromure は その取引の反対側に立ち、さらにトークンを部屋の外へ出す。


出典:Schwarzl, Xiao, Pedersen, Ainsworth, Topham「Remote-Timer-as-a-Service: Efficient Microarchitectural Leakage in the Cloud with Remote Timers」(arXiv:2608.17043、2026年8月17日) · Cloudflare「A revisit of remote Spectre attacks on Cloudflare Workers」(2026年8月19日) · Cloudflare「Sandboxing AI agents, 100x faster」(2026年3月24日) · The Hacker News「Cloudflare Workers Spectre Attack Leaks JWT From Co-Located Worker at 12 Bits/Second」(2026年8月19日)