Cloudflare 推理缓存故障导致跨用户内容泄露
据摘录,Cloudflare Workers AI 的 GLM-5.3 在十三天内出现长提示词响应混入其他客户对话的故障。根因涉及缓存容量小于宣称的上下文窗口,以及被拒请求错误发送传输完成信号;上线前测试未验证极限长度下的响应内容。
AI 深度解读
HTTP 200、流式输出正常、响应时间达标,AI 接口仍然可能正在返回别人的数据。原文讲的是 Cloudflare Workers AI 上 GLM-5.3 的一次跨客户内容泄露:缓存容量不足,加上错误的阶段交接信号,让超长请求读到了其他请求留下的状态。
这起事故值得程序员花几分钟读,因为漏洞不只出在推理引擎里,也出在测试的验收标准里:团队确认了接口能回答,却没有确认答案来自当前请求。
百万 token 的窗口,为什么装不下合法请求
据原文,2026 年 8 月 27 日至 9 月 9 日的 13 天里,部分发送给 GLM-5.3 的长提示词,得到了混入其他客户对话内容的回答。Cloudflare 于 2026 年 10 月 26 日披露了完整根因,共从日志中识别出 155 条受影响响应。
问题首先出在两个容量没有对齐。
Workers AI 为 GLM-5.3 宣传的上下文窗口是 1,048,576 tokens,支撑预填充阶段的 KV-cache 池却只配置了 681,280 tokens,相差约 367,000 tokens。客户可以按公开窗口提交请求,底层缓存却无法容纳其中最长的那一部分。
这里的 KV cache 是模型处理上下文时保存的注意力中间状态,不是常见的接口响应缓存,也不要把标题里的 KV 理解成普通键值存储产品。
推理引擎会利用这些中间状态继续生成答案。缓存页一旦对应错了请求,模型就可能把其他请求留下的信息当成当前上下文使用。
容量不足原本可以表现为一次明确拒绝。但这次事故又叠加了第二个错误,把资源不足变成了跨客户数据泄露。
请求已经被拒绝,为什么还能生成答案
他们使用的 SGLang 采用预填充与解码分离架构,即 disaggregated prefill/decode:一组机器处理输入、构建 KV cache,另一组机器读取这些状态并生成 token。
两组机器之间需要交接。解码节点必须知道,自己要读取的缓存是否已经准备好。
当请求超过实际缓存池容量时,SGLang 本应直接拒绝。实际发生的却是:引擎把超大请求替换成只有一个 token 的占位请求,随后仍向解码节点发送「transfer complete」信号,表示缓存传输完成。
解码节点信任了这个信号,开始读取对应位置。但完整的新缓存并没有写进去,那里可能仍是另一位客户此前请求留下的旧缓存页。
真正危险的组合,是缓存容量不足之后,失败路径仍然发出了成功信号。
原文称,155 条受影响响应对应的提示词全部超过 681,280 tokens。这个边界与真实缓存容量一致,支持了上述故障解释。不过,它是已识别响应的统计,不能据此推算受影响客户数量,也不能把 155 当成日志之外绝无遗漏的保证。
修复有两层,测试也得检查答案
问题由与 Knostic 合作的安全研究员 Gadi Evron 发现。他看到回答引用了当前会话中合法用户没有提供过的上下文,于 2026 年 9 月 8 日通过 HackerOne 报告。
Cloudflare 用 25 分钟复现,在确认问题后约 40 分钟将模型下线。原文称,内部宣布事故的当天就部署了修复:把缓存池扩到约 204 万 tokens,同时修补 SGLang 的错误传输信号。
两项修复分别处理容量和交接逻辑。只扩容,不能证明拒绝路径已经正确;只修信号,也不能让实际容量自动满足公开承诺。
上游修复对应 PR #36988 和 #38935,分别进入 v0.5.20、v0.5.21,完整修复于 2026 年 10 月 19 日纳入 v0.5.22。对于自建服务的团队,原文提供的是版本线索,具体部署是否包含完整补丁仍需核对。
更贴近日常开发的教训在测试上。Cloudflare 的上线前测试检查了 HTTP 状态码和流式响应,却没有验证超过真实缓存容量后,回答内容是否仍与输入一致。
作者随后检查了自己团队针对有最大输入限制服务的压测脚本:全部检查状态码和耗时,没有一个检查接近输入上限时的回答语义。他们补了一项测试,连续发送两个内容明显不同、接近公开上限的长提示词,确认第二次回答没有引用第一次独有的信息。
这是一项具体改动。但原文没有展示测试代码、重复运行结果,也没有给出检测效果的对照数据。「成本低、能够捕获这类故障」应视为作者的经验判断。
我的判断
我认同作者最核心的提醒:AI 接口的测试需要覆盖内容归属。状态码、连通性、流式输出都正常,无法证明模型使用的是当前请求的数据。
不过,「回答连贯」和「没有泄露」需要分开检查。串入其他客户信息的回答也可能很通顺。比笼统判断答案是否合理更明确的做法,是给两组测试上下文放入不同的专属标记,检查后一次输出是否出现前一次标记。
这类测试也有边界。模型未必主动复述读到的信息,连续请求也未必复用同一组缓存页。因此,两次调用没有串内容,不能证明整个服务已经满足租户隔离要求。它适合补充黑盒验收,服务提供方仍需验证缓存归属和异常交接路径。
对托管模型用户来说,作者建议确认「公开窗口是否匹配实际缓存」是合理诉求,但一般业务团队很难直接看到供应商的内部配置。相比自己能控制缓存和推理引擎的团队,托管用户更依赖供应商的说明与证据。
事故范围也应保持克制。Cloudflare 表示没有发现蓄意利用的证据,其他 Workers AI 模型没有同样的容量错配,但原文没有确认每位受影响客户是否都收到单独通知,也不知道其他采用类似 SGLang 架构的供应商是否完成排查。
此外,Cloudflare 最初曾把实际执行的窗口说成 1,310,720 tokens,随后更正为文档中的 1,048,576。讨论边界测试时,应使用更正后的数字。作者结尾还推广了自己的隔离式 VM 产品,这属于商业主张,不能直接当作替代架构已经解决此类问题的验证。
能拿来做什么
- 给前端 AI 产品背后的 Node 调用链补一项接近输入上限的内容检查,使用人工构造的上下文和专属标记,明确断言回答不能引用上一请求独有的信息。
- 如果使用托管推理服务,向供应商确认超限请求如何拒绝、公开窗口如何验收,以及预填充失败后是否还能触发解码;这些问题比只询问接口可用率更贴近本次故障。
- 如果自建 SGLang 服务,核对 #36988、#38935 及 v0.5.20、v0.5.21、v0.5.22 的补丁覆盖情况,并检查拒绝、截断请求在两个阶段之间如何传递状态。
- 如果曾在 2026 年 8 月 27 日至 9 月 9 日向该端点发送超过约 681,000 tokens 的提示词,回查现有日志中的异常回答,精确筛选时使用 681,280 tokens,并把无法解释的外来内容作为潜在数据暴露线索。