一条 200 不代表安全:GLM-5.3 缓存跨租户泄露,API 采购要补三张审计表
155 条 200,把别人的对话发了出去
Cloudflare 与开源推理引擎 SGLang 的维护团队 10 月 26 日联合披露了一起跨租户数据泄露:Workers AI 上托管的 GLM-5.3(@cf/zai-org/glm-5.3)在 8 月 27 日上线起至 9 月 9 日修复止的窗口内,共 155 条响应混入了其他客户请求的内容。这些响应全部来自超过 681,280 个 token 的提示词——而该模型对外宣称的上下文窗口是 1,048,576 个 token。

出事的根源是两层问题叠加。第一层是配置不匹配:GLM-5.3 部署时上下文按 104 万 token 开放,但预填充 GPU 上的 KV 缓存池实际只能装 681,280 个 token,Cloudflare 自己承认上线前就知道这个差异,只是预期引擎会对超长请求报错,而长上下文测试都返回了正常的 HTTP 200,于是放行了。第二层是 SGLang 在预填充/解码分离模式下的一个拒绝路径缺陷:装不下缓存池的请求被内部标记为拒绝、提示词被替换成单 token 占位符,但请求没有中止,占位符的缓存照样传到了解码节点;解码端读的是 8 个预留页面,其中只有第一页属于当前请求,其余 7 页还躺着上一个用户的数据。
修复与时间线:40 分钟下线,25 分钟复现
9 月 8 日,安全研究者 Gadi Evron(Knostic)通过 HackerOne 报告了问题,Cloudflare 次日开始复现,25 分钟内用两个独立账户确认了泄露,宣布事故后 40 分钟内把模型下线,当天 19:40 恢复服务。修复做了两件事:一是把缓存池扩到约 204 万 token,约为上下文窗口的两倍,让合法请求永远走不到拒绝路径;二是给引擎打补丁,让带拒绝状态的请求在分离准入队列中直接终止并返回原始错误。这个缺陷 7 月 6 日就作为 issue #30233 被报告过,修复先后进入 SGLang v0.5.20、v0.5.21(10 月 2 日)和 v0.5.22(10 月 19 日)。Cloudflare 表示未发现蓄意利用的证据,受影响的 155 条请求在时间和数量上符合普通长上下文使用特征,Workers AI 上其他模型均未受影响。
站在 API 采购与分发的一侧,需要补三张审计表
这件事的采购侧含义比事故本身更值得琢磨。它暴露的不是某家模型厂商的问题,而是 API 聚合分发链路里一个通用盲区:HTTP 200 和响应速度都不能证明多租户隔离是可靠的——泄露发生时,客户端拿到的是连贯、快速的正常回复。对使用长上下文的聚合分发方和 API 采购方,建议补三张表:
第一张,供应商事故面。确认你所采购或转发的长上下文端点,在 8 月 27 日至 9 月 9 日之间是否使用过 Workers AI 的 GLM-5.3;若是,梳理当时超过 68 万 token 的请求清单,评估其中的敏感数据(代码、客户资料、密钥)是否可能随那 155 条响应外溢。
第二张,自建层引擎版本表。凡是自己用 SGLang 做分发或私有化服务、尤其开了预填充/解码分离模式的,官方建议直接升到 v0.5.22 以上,并在每次变更量化方案、并行策略或内存占比后,从引擎启动日志核对 KV 缓存池是否大于上下文长度——这正是本次事故里 Cloudflare 自认漏掉的那道检查。
第三张,供应商响应 SLA 表。把事故下线时长、复现时长、协调披露时限写进采购条款:本次 Cloudflare 40 分钟下线、当天恢复、10 月 26 日联合披露,可以作为参照基线;同时要求供应商出具多租户隔离的验证方法(本次是金丝雀标记测试加研究者复现脚本),而不是只看功能测试通过。
从成本角度看,Cloudflare 把缓存池扩到两倍上下文属于典型的用显存换安全边际,而它自研的完整性校验原型吞吐和尾延迟开销不到 1%。对分发平台来说,这条的边际成本远低于一次数据泄露的合规代价,值得直接照抄。
值得留意的是,SGLang 维护者同时披露了另一类同类风险:请求在传输中途被中止时,滞后的 RDMA 写入可能落在已被复用的缓存页上,造成单向跨请求污染。这意味着即使本次配置问题修好,分离架构下的缓存生命周期管理仍是需要持续跟版本的长期课题。
来源:Cloudflare 官方博客、SGLang/LMSYS 官方安全更新、Unite.AI 报道(数据经多方交叉认证)。