返回趨勢情報
趨勢情報

Cloudflare GLM-5.3:155 則回覆讀到別人的 KV 快取;池子 681,280 對上窗口 104 萬,賞金 7,500 美元

2026年10月28日
易賺Ai團隊
13 分鐘閱讀
#Cloudflare#GLM#資訊安全#KV快取
Cloudflare GLM-5.3:155 則回覆讀到別人的 KV 快取;池子 681,280 對上窗口 104 萬,賞金 7,500 美元

客戶送進一段超過 681,280 個 Token 的提示詞,Cloudflare Workers AI 上的 GLM-5.3 回了 HTTP 200。prompt_tokens 對得上那串很長的輸入。回覆比「真的把八頁 KV 快取 做完 prefill」該花的時間更短,內容卻夾了上一個人留下的提示詞與半成品生成。

Cloudflare 工程師 Kevin Flansburg、Michelle Chen 寫的事故報告,把範圍釘死:模型識別碼 @cf/zai-org/glm-5.3,時段 8 月 27 日到 9 月 9 日,受影響回覆 155 則,全部對應長過 681,280 token 的提示詞。公司說扣掉自己的測試和回報者之後,時間與量都像普通的長上下文使用,沒有看到有人反覆利用。沒有其他 Workers AI 上的模型中招。GLM 是 Z.ai 的文字生成模型,賣點寫成 agentic coding;Cloudflare 把開源權重載到自己的 GPU 上提供服務。

Knostic 執行長 Gadi Evron 9 月 8 日 23:11 UTC 經 HackerOne 回報。他後來在 Infosec Exchange 寫:大型請求可能回傳另一個客戶推理工作階段的內容。HackerOne 公開頁面顯示這筆 Cloudflare Public Bug Bounty 已結、賞金 7,500 美元。

兩個洞疊在一起

第一個洞是設定。Cloudflare 把 GLM-5.3 的上下文窗口設成 1,048,576 token,prefill GPU 上的 KV 快取池卻只裝得下 681,280。池子大小不是設定檔裡的一個欄位,SGLang 啟動時用載入權重之後剩下的 GPU 記憶體去算;模型對外宣稱的上下文長度是另一個設定。沒有機制強迫兩者一致。啟動日誌會印池子大小,也有對應指標。Cloudflare 寫:上線前就知道這個落差。團隊以為引擎會對裝不下的提示詞回錯誤。長上下文壓測拿到的是成功的 HTTP 狀態碼和沒有錯誤幀的串流本體,所以沒當成問題。報告自己寫的測試缺口是:只核了 HTTP 狀態碼和引擎效能,沒核模型輸出和連貫性。

第二個洞在 SGLang 的拆分 prefill/decode 模式。提示詞比池子長時,排程器會拒絕這筆請求,Req.set_finish_with_abort 把錯誤記下來,把提示詞換成一個 token 的佔位符,好讓請求沿著普通批次路徑流掉、不必真的配記憶體。單機部署這條路是通的:佔位符跑完,客戶拿到錯誤。拆分模式裡,prefill 和 decode 兩邊的入場佇列檢查的是請求有沒有結束,不是有沒有被拒絕。被拒絕的請求把拒絕存在 to_finish,不是 finished_reason,finished() 仍回 False,看起來還活著。

接下來的七步,官方寫得很機械:

  1. 路由器告訴 decode 節點提示詞長度(示意圖裡 8 頁),decode 預留 8 頁 KV。
  2. Prefill 入場佇列放行任何 req.finished() 為 False 的請求,被拒絕的那筆也進去。
  3. 拒絕早已把提示詞換成單 token,prefill 對那一個 token 做一次極短的前向。
  4. Prefill 送一頁 KV 給 decode,並發出「傳輸完成」。
  5. Decode 入場佇列用同一個 finished() 檢查,接受交接。
  6. Decode 開始生成,注意力讀完預留的 8 頁。只有第 0 頁是這筆請求寫的。第 1 到第 7 頁仍是稍早請求留下的內容:其他人的提示詞和部分生成。
  7. 客戶拿到 HTTP 200,不是 400。

KV 頁在請求之間目前不會清零。下一筆拿到同一頁的請求直接覆寫。官方說這在推理引擎裡很常見,也是衝效能必要的做法,前提是引擎自己把頁的所有權和生命週期追清楚。拆分模式下,所有權還跟遠端 prefill 節點共享——那邊同時握著對同一頁的可變參照。傳輸走 RDMA,經 Mooncake。

這個引擎洞不是新的。另一個使用者 7 月 6 日就在 SGLang 開了 issue #30233。Cloudflare 寫:從 v0.5.10 起就在跟 SGLang 團隊標這類問題,這次事故把已經在做的修補加快。補丁進了 v0.5.20,後續在 v0.5.21、v0.5.22。公司建議所有依賴 SGLang 的營運方升到 v0.5.22 或更後。

Workers AI 上其他拆分部署,prefill 和 decode 兩邊的 KV 池都大於上下文長度,請求走不到拒絕路徑。這次只有 GLM-5.3 踩中。官方已把引擎修補和後面的加固套到所有用 SGLang 的模型,新部署檢查也強制這些條件。

時序(全部 UTC)

時間發生什麼
8 月 27 日GLM-5.3 在 Workers AI 上線,prefill KV 池小於上下文窗口。暴露從上線就存在。
9 月 8 日 23:11HackerOne 收到回報。
9 月 9 日 08:00Cloudflare 開始核對。
9 月 9 日 13:22宣告資安事故。Product Security 用兩個獨立帳號,25 分鐘內重現外洩。
9 月 9 日 14:00GLM-5.3 設為私有,請求回 HTTP 400。狀態頁更新。宣告事故後 40 分鐘內下線。
9 月 9 日 14:35根因定為 prefill 池小於上下文長度。放大池子的 canary prefill 節點確認不受影響。
9 月 9 日 14:52所有 prefill 節點滾到修正後的設定。
9 月 9 日 19:04完整部署重建:修正設定,加上 Cloudflare 寫的引擎補丁,讓被 prefill 排程器拒絕的請求正確回錯誤。用回報者的重現腳本驗證。
9 月 9 日 19:40模型恢復公開。
9 月 10 日 23:30與 SGLang 維護者(RadixArk CTO 與核心工程師)開會,談上游修補。
9 月 11–19 日額外加固滾到所有生產 SGLang 部署。
10 月 2 日SGLang v0.5.21。
10 月 19 日SGLang v0.5.22。
10 月 26 日與回報者、RadixArk 協調後公開。

設定面的修復:把 GLM-5.3 的配置改成跟 GLM-5.2 一樣,清出夠多 GPU 記憶體,讓 prefill KV 池裝大約 204 萬 token,約等於 1,048,576 token 上下文長度的兩倍。能通過上下文窗口的提示詞,現在一定裝得進池子,拒絕路徑對合法請求走不到。

引擎面的修復:帶有待處理拒絕的請求,在拆分入場佇列就被退回,帶著原本的錯誤,還不做 bootstrap、分配或 KV 傳輸。Cloudflare 把這條提上游當 #38704,decode 節點還要核對傳過來的 token 數等於自己預留的數。同類修補其實 9 月 6 日已以 #36988 合進 SGLang main,當時還沒發版。維護者後來又合了 #38935,更早拒絕這類請求。

自架的人要改什麼

Cloudflare 對拆分 prefill/decode 的 SGLang 營運方列了五條,不是建議看看就算:

  1. 每次改權重、量化、平行度或記憶體比例之後,從引擎啟動日誌量 KV 池,跟上下文長度比,prefill 和 decode 節點都要比。池子比較小,就把上下文長度往下調到裝得下。不要靠代理層去擋,也不要假設引擎會拒絕裝不下的東西。這是他們自己沒強制做的那一步。
  2. 升到含 #36988 與 #38935 的建置(v0.5.22 或更後),讓超長請求在交接前就被拒,不管池子多大。
  3. 兩個角色都開 deferred KV release(#41023 之後是預設),並把 Mooncake 傳輸批次設上限,避免單次逾時留下無界的尾寫。
  4. 模型支援的話打開損壞偵測。--disaggregation-enable-kv-checksum 與 --kv-canary 還沒覆蓋所有架構。查日誌確認請求真的在被核。Cloudflare 寫正在跟 SGLang 把這兩項擴到更多架構,包括 GLM-5.3、GLM-5.3 Flash 和 DeepSeek V4。
  5. 負載平衡不要在第一個 token 之前就因客戶斷線而 abort,避免觸發要跨節點協調的中止。

頁級所有權檢查還在原型。Cloudflare 夏天做過:每個實體 KV 頁帶一個重新分配就會變的標籤,每筆請求記下自己預期的標籤,decode 讀快取前核對。測試裡對吞吐量和尾部延遲的代價低於 1%。8 月中旬在 GLM-5.2 測過,不久因可靠度問題關掉。原型綁特定注意力後端和模型架構,不能當通用修法。per-transfer checksum(#39500)是第一步,只核 prefill 到 decode 的交接。頁級標籤會核每一次讀,包括交接很久之後的讀。把頁在釋放時清零的草案是 #46435,還沒合。

The Injection 把影響面寫成問答:從來沒送過長於 681,280 token 提示詞到 GLM-5.3 的帳號,不在這 155 則裡。Cloudflare 客戶端不用自己打補丁,平台修補 9 月 9 日就上了。自架拆分 SGLang、且 KV 池小於上下文長度的人,才是還暴露的那群。單機部署官方說同一條拒絕路徑是對的。

這次洩的不是權重,是別人的上下文

同月稍早,php2shell 走的是模型找出藏了十年的遠端執行洞。Google Agent Compute Engine 則把每顆 agent 關進硬體隔離的 microVM。這次 Cloudflare 的洞更土:共用 GPU 記憶體上的 KV 頁沒清、所有權追丟,讀到的是上一筆請求留下的中間狀態。DeepSeek 把 KV 快取砍到四分之一 時,討論的是省記憶體;這次討論的是省下來的那塊記憶體,會不會變成別人的提示詞。

Prefill 與 decode 拆開,是現在衝長上下文推理的常見架構:一組 GPU 處理提示詞、產出 KV,再經 RDMA 交給另一組 GPU 生成。賣 100 萬 token 窗口的型錄數字,和啟動日誌裡實際印出來的池子大小,可以不是同一個數。Cloudflare 的長上下文測試拿到 HTTP 200,所以沒把兩者對上。下一次改量化、張量平行或 CUDA graph 大小,池子又會變,官方自己也說「只靠把池子加大很脆」。

Cloudflare 在報告末段把同類洞再往上抽一層。RDMA 把資料從一台機器的記憶體直接拷到另一台。兩邊必須對「寫到哪、多大、何時寫完」看法一致,否則接收端會讀錯頁。這次是分散式系統的一致性失敗:prefill 以為自己在清退一筆被拒的請求,decode 以為自己拿到完整提示詞的 KV。公司說會把形式化方法用到 KV 快取傳輸引擎,目標是把生產環境裡走 Mooncake 的 SGLang 分散式 KV 系統建模,追任何偏離安全性質的地方。官方自己寫:證明器填不滿所有縫,但把能證的證完,剩下的缺口比較好盯。

協調揭露跟 SGLang 團隊的部落格同一天出來。Evron 點名 Cloudflare 的 Avishek Sarkar、Kevin Flansburg、Michelle Chen,說希望所有漏洞賞金計畫都這樣運作。Workers AI 的資安問題,官方入口仍是 hackerone.com/cloudflare。自架營運方能核的,是啟動日誌裡的池子數字、是不是 v0.5.22、以及 checksum/canary 有沒有真的打在你跑的那個架構上。型錄上的 100 萬 token,不夠當隔離證明。