返回所有文章
發佈於 · 作者 Renaud Deraison

那個 token 從隔壁的行程漏了出來

研究人員從相鄰的一個 Cloudflare Worker 裡以每秒 12 位元拉出了一枚 JWT,沒有逃出沙箱,也沒有動用任何記憶體安全漏洞。isolate 的邊界始終沒破。祕密還是越過去了,走的是底下的硬體。如今雲端平台正把同一道邊界拿來執行 AI 代理程式寫出來的程式碼。Bromure Agentic Coding 把線畫得更低一層,並且乾脆不把你的憑證放進那個盒子裡。

某個租戶的 JavaScript 向 CPU 問了幾百萬個形狀經過設計的問題,然後從答案裡讀出了另 一個租戶的驗證 token。它始終待在平台為它畫的邊界之內,跑的是普通的 JavaScript,而 那道邊界從頭到尾都在盡責。

8 月 17 日,一組研究人員發表了 Remote-Timer-as-a-Service,19 日 Cloudflare 也貼出 自己對這項研究的說明。 他們從正式環境中一個同處一地的 Cloudflare Worker 裡,以最高每秒 12 位元、99.16% 的準 確率,拉出了一枚 JSON Web Token,也就是服務用來確認你身分的那串簽章字串。針對同一個 平台,先前公開的成果來自 2021 年,速度是每分鐘 2 位元。到了 360 倍的速率,你就跨過了 奇聞與被竊憑證之間的那條線。

Cloudflare 已經修好了,三年來沒有發現任何人用過的跡象,也表示沒有客戶資料遭到存取。 往下讀,看看這場攻擊自始至終都不必做的事。

沒有任何東西非壞不可

Cloudflare Workers 用很少的硬體跑很多租戶,做法是省掉平常把他們隔開的那樣東西。用 Cloudflare 自己的話說,Workers「在同一個作業系統行程之內,以彼此分離的 V8 isolate 執 行多個租戶的程式碼」。isolate 是 JavaScript 層級的容器:自己的堆積、自己的全域、沒有 共享記憶體、沒有執行緒。它在幾毫秒內啟動,而那正是重點所在,因為行程隔離會讓你在每 一個請求上都付出冷啟動的代價。

攻擊者需要的是跑在某個 isolate 裡的程式碼。把受害者弄進同一個行程才是漂亮的部分:攻 擊者的 Worker 去呼叫受害者。就像研究人員寫的,從攻擊者的腳本用 fetch("https://victim.example") 呼叫受害者,「多數情況下會讓排程器在完全相同的行程 裡啟動一個受害者 worker 的實例」。你不必等待同處一地,你把它召喚出來。

從這裡開始就是 Spectre 了。誤導分支預測器,讓 CPU 推測執行一次它本來絕不該做的讀取, 再量測快取,看它讀到了什麼。Cloudflare 早已花了數年把這件事變難:沒有 SharedArrayBuffer、沒有執行緒、計時器被凍結並粗化,讓你量不到小到像一次快取命中那 樣的東西,還有 Dynamic Process Isolation(DyPrIs),它盯著硬體效能計數器,把任何聞起 來像 Spectre 的東西挪進獨立行程。

研究人員把這些一個個繞了過去。

時鐘來自外面。連到 Durable Object,或連到網際網路上一台普通時間戳伺服器的 WebSocket, 就能在一個拒絕給你時鐘的平台裡拿到次毫秒等級的解析度。接著他們沒有去提高解析度,而 是把訊號放大:L1 快取的 tree-PLRU 置換策略沿著二元樹指標走,所以一次快取事件可以被變 成一長串命中,或一長串失誤。他們寫道:「單一快取事件的時序可以被任意放大。」只要你把 要計時的東西弄得夠大,模糊的時鐘就夠用了。

DyPrIs 錯過了兩次。它是在呼叫「結束之後」才隔離腳本,而靠 keep-alive 訊息維持存活的 Durable Object 可以跑上好幾個小時、最長到一整天,於是這個 exploit 在一次永不結束的呼 叫之內就完成了。它還會用 iTLB 存取次數把分支預測失誤正規化,而用 Cloudflare 的話說, 「我們的遠端計時器就是一個大型 I/O 迴圈,那些 WebSocket 流量會把 iTLB 活動撐大」。研 究人員把自己的分母養大,直到警報顯示一切正常。

剩下的都是水電工程:一個推測型別混淆的 gadget 用來洩漏 isolate 的根位址,對 typed array 的 backing store 做 64 位元指標混淆,把它變成任意讀取,然後是受害者的 JWT,一次 一個位元。

一個 OS 行程。兩個租戶。一道用 JavaScript 做成的邊界。作業系統行程攻擊者 isolatefetch("https://victim.example")把受害者召進這個行程普通的 JavaScript,沒有原生碼受害者 isolate自己的堆積、自己的全域沒有共享記憶體、沒有執行緒JWT 就在它的位址空間裡來自外面的時鐘連到時間戳伺服器的 WebSocket次毫秒等級的解析度平台自己的計時器仍舊凍結共用 CPU:分支預測器、L1 快取、tree-PLRU 置換isolate 的邊界在這一層並不存在 — 一次快取事件被放大成長到連模糊時鐘也讀得到的一串結果:受害者的 JWT,一次一個位元 — 最高 12 bit/s、準確率 99.16%,2021 年的 360×
攻擊者始終沒有離開自己的 isolate。它呼叫受害者,好讓排程器把對方放進同一個行程;向平台之外的一個 WebSocket 借來時鐘;把單一快取事件放大成可量測的一長串;再透過兩個 isolate 共用的硬體,一位元一位元讀出鄰居的 token。

修補比發現說得更多

Cloudflare 推出了三項緩解措施。請把它們合起來讀。

他們整合了 V8 Sandbox,把原始的 64 位元指標從 JavaScript 堆積區域裡移走,殺掉了 typed array 那個 gadget。他們教會 DyPrIs 把長壽的 Durable Object 與 I/O 密集的工 作負載當成第一級的安全案例,而不是雜訊。他們還部署了 Memory Protection Keys,在共 用行程之內,把每個租戶的堆積放到一道由硬體強制的存取邊界後面。

三項全都往 JavaScript 底下伸手,去找比 JavaScript 語意更硬的東西,而第三項直接落在 CPU 本身。Cloudflare 坦白表示 V8 Sandbox「並不是完整的 Spectre 緩解措施」。用加上一道 硬體層級邊界的方式來修補語言層級邊界的工程師,已經告訴你他們認為真正的線在哪裡。

一個談代理程式編碼的部落格,寫起了 CDN

isolate 已經離開 CDN 了。3 月,Cloudflare 以 Sandboxing AI agents, 100x faster 為題推出 Dynamic Workers,一種在執行期用一秒前還不存在的程式碼啟動 Worker 的做法。如 果你跑過會自己寫、自己執行腳本的代理程式,你懂那個動機:「如果一個代理程式(或一個 MCP 伺服器)要執行 AI 即時產生的程式碼來完成任務,那些程式碼總得跑在某個地方」,而且 「你不能直接在自己的應用程式裡對 AI 產生的程式碼下 eval()」。

Cloudflare 在同一篇文章裡點名了那個機制:「Dynamic Workers 使用的,正是整個 Cloudflare Workers 平台自八年前推出以來一直賴以建立的底層沙箱機制:isolate。」理由是速度。一個 isolate 用幾 MB 記憶體在幾毫秒內啟動,大約比容器快 100 倍、記憶體效率高 10 到 100 倍, 於是「每個請求一個全新沙箱」變得負擔得起,而不必去用一個你反覆重用、每一輪都更弱一點 的溫池。

Cloudflare 對代價說得很坦率。他們自己的 beta 文章用八個字講完:「V8 的安全漏洞比 hypervisor 的漏洞更常見。」 那是在有人漏出 token 的好幾個月之前寫下的。

所以這裡的故事是一樁交易,由做這筆交易的人自己寫下來,如今又被研究人員標上了每秒 12 位元的價格。問題落到了其他所有人身上。當被放進沙箱的程式碼是模型寫的,被某個套件或某 個網頁講的話塑形過,然後被留在一枚 bearer token 旁邊跑著,那是你想要的交易嗎?

Bromure 把線畫在 hypervisor

Bromure Agentic Coding 不會把你的代理程式放進一個語言層級的容器,跟別人的程式碼擠在一 起。每個工作區都是一台跑在 Apple Virtualization.framework 上的 Linux 虛擬機,只支援 Apple Silicon:自己的核心、自己的客體記憶體、自己從唯讀基底映像複製出來的磁碟。沒有共 用行程,就沒有可以召喚的同居租戶;你的代理程式所在的那道邊界是 hypervisor,也就是 Cloudflare 自己那個比較裡漏洞比較少的那一邊。

那是架構層面。真正會讓這場攻擊變得毫無意義的東西更窄,而且還要再往裡走一步。

token 從來就不在盒子裡

研究人員帶走的,是一枚躺在受害者位址空間裡的 JWT,也就是一個執行中的服務放置自己所用 憑證的地方。他們沒有拿到 shell,也沒有拿到 root。

Bromure 的工作區不會把憑證放在那裡。

一個設定檔裡的每一個祕密都留在你的 Mac 上。這涵蓋 ANTHROPIC_API_KEY、GitHub 個人存 取權杖、AWS 存取金鑰、kubeconfig 的 bearer token、容器登錄檔的 Basic-auth blob,以及 Linear 金鑰。Bromure 注入虛擬機的是假的:一個 brm_… 佔位字串、一張用完即丟的用戶端憑 證、一段衍生出來的 Basic 字串。代理程式讀它,SDK 讀它,gitkubectldoctl 也 讀它,工作照樣跑得通,因為主機上的 MITM proxy 會在外送請求上換回真正的值。AWS 那邊還 多鎖了一圈:主機會用真正的材料重新簽署 SigV4 請求,所以任何繞過 proxy 的東西從 Amazon 拿回來的是 InvalidSignatureException,而不是一次成功的呼叫。

於是,一個在那台虛擬機裡握有完美任意讀取能力的攻擊者,也就是研究人員花一整篇論文才建 出來的那個 primitive,讀到的是誘餌。位元組確實在那裡,能被解析,看起來像一把金鑰,卻 在機器外買不到任何東西。不論隔離邊界是否完美無瑕,你都能得到這個結果,因為工作區裡根 本沒有值得偷的東西。

傳統做法:邊界是軟體,而祕密就在裡面isolate 裡的代理程式碼和其他租戶共用一個 OS 行程真 token 就在它的位址空間裡底下的共用硬體快取與分支預測器把邊界擋下的位元帶了過去鄰居讀走 token12 bit/s、99.16%BROMURE:邊界是 hypervisor,而祕密在它的另一側工作區虛擬機自己的核心與記憶體,沒有同居租戶ANTHROPIC_API_KEY=brm_…假的 — 任意讀取讀到的是誘餌MITM proxy,主機端把假的換成真正的值egress 規則決定位元組能去哪裡每次使用可選擇跳出同意對話框真正的 API看到的是真憑證而且是從你的Mac 送出去的每一次替換、每一條被允許與被拒絕的連線:Window → Security Timeline 裡的一列,寫在虛擬機之外
傳統上,鄰居與你的憑證之間就只隔著沙箱邊界,而憑證就放在沙箱裡面。在 Bromure 的工作區裡,邊界是 hypervisor,憑證放在它的另一側:客體握著一份假的,而客體構不到的那個 proxy 會在傳輸線上換成真正的值。

每秒十二位元,還是得有地方可去

側通道只是外洩的一半。另一半是一條往外的路,而每秒 12 位元代表這條路得開著一陣子。一 枚 400 字元的 token,意味著要往攻擊者控制的目的地送上好幾分鐘的流量。

一個 Bromure 設定檔帶著自己的 egress 規則,寫成一小段 pf 風格的政策,並以表格的形式編 輯。強制執行的是你的 Mac,發生在虛擬交換器與 proxy 裡,客體內部的任何東西都沒有發言 權:被拒絕的連線會收到 reset,而這個決定會帶著主機、IP、連接埠與判定,變成 Window → Security Timeline 裡的一列 egress.firewall。跑在工作區裡的程式碼,站在 它想改的那些規則的錯誤那一側。

你也可以在每一次動用真憑證時按住它。對每個祕密打開 Require approval to use:模型的 API 金鑰、SSH 簽章、GitHub 與 GitLab 與 Bitbucket 的權杖、每個 kubeconfig 情境、 DigitalOcean、每一次 AWS SigV4 簽章、每個容器登錄檔,以及你自己加上的任何手動權杖規 則。替換會就地停下,等一個 macOS 上的對話框,你可以授權五分鐘、一小時,或整個工作階 段。客體永遠沒有機會回答那個問題。

交易本身才是故事

isolate 是很好的工程,而 Cloudflare 的處理方式正是你會希望看到的:協同揭露、三項實在的 緩解措施、對 V8 Sandbox 涵蓋什麼與不涵蓋什麼絕不打太極。每秒數百萬個請求不跑在容器上, 是有原因的。

冷啟動是在 CDN 上贏得這場爭論的東西,但你的編碼代理程式並不是在四毫秒內回答一個 HTTP 請求。它會跑一個小時,裝上沒有人稽核過的套件,執行模型寫的測試套件,讀那些很想跟它說上 幾句話的網頁。不論是什麼在跑這個工作負載,它在整段期間都握著你的權杖,而關於它所執行的 程式碼,你唯一知道的事情就是那不是你寫的。

對這樣的工作來說,幾百毫秒的虛擬機開機時間不是值得省下的成本。Cloudflare 已經公布了匯 率:V8 的漏洞比 hypervisor 的漏洞更常見。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 日)