方法与实践 可动手 重点 10月29日 周四 #inference#safety#infra#open-weights

Cloudflare 复盘:KV 池小于上下文加 SGLang 缺陷,导致跨客户数据泄露

Cloudflare 10 月 26 日公布复盘:Workers AI 上的 GLM-5.3 声明 1,048,576 token 上下文,但 prefill 节点的 KV 池只有 681,280 token。SGLang 在 prefill/decode 分离模式下把放不下的请求标为 rejected 并换成 1 个 token 的占位,但入口队列只检查 finished,请求仍被送到 decode,读到了其他请求残留的 KV 数据,客户端还收到 HTTP 200。8 月 27 日至 9 月 9 日间共有 155 条响应受影响。

两个原因叠加,让超长请求带着别人的数据返回 200
  1. 1配置不匹配声明的上下文大于 KV 池容量
  2. 2Rejected超长请求被标 rejected,换成占位
  3. 3Admission只查 finished,请求仍被放行
  4. 4Decode读到他人残留 KV,返回 HTTP 200

结构来自 Cloudflare 复盘的根因说明

要点

  • 上线前团队已知池子偏小,但长上下文测试只看 HTTP 状态,没有检查输出内容
  • 修复:KV 池扩到约 2.04 million token(约为上下文的两倍),引擎在入口直接按 rejected 返回错误
  • Cloudflare 建议所有运维者升级到 SGLang v0.5.22 或更高,并可开启 KV 传输校验和
  • 建议每次改权重、量化、并行度或显存设置后,在启动日志里核对 KV 池容量与上下文长度
为什么值得关注

自部署 SGLang、vLLM 等推理引擎的团队都可能踩到「配置不匹配 + 引擎边界缺陷」的组合;复盘里的自查项(版本、池容量、输出级测试)今天就能照做。

配套实验

已验证 检查 7/7 通过 GitHub Actions 实际运行 · Python 3.12.15 · 耗时 0.1s
玩具模型复现:被拒绝的超长请求进入 decode 导致跨请求泄露

按 Cloudflare 复盘描述的机制,用纯 Python 模拟 KV 池小于上下文长度、入口只检查 finished 时的泄露,并对比引擎修复、扩大 KV 池和 canary 检测三种手段的效果。

结论玩具模型中泄露只发生在「池子小于上下文 + 引擎只查 finished」的组合,状态码测试全过而 canary 测试全部抓到

…
METRIC: 泄露响应数(小池子 + 原始引擎) = 27 个
METRIC: 泄露响应数(小池子 + 引擎修复) = 0 个
METRIC: 泄露响应数(大池子 + 原始引擎) = 0 个
METRIC: 泄露响应数(大池子 + 引擎修复) = 0 个
METRIC: 只看状态码的测试报警数 = 0 个
METRIC: canary 测试报警数 = 27 个
[PASS] 池子小于上下文长度且引擎只查 finished 时,会出现返回 200 但带着别人数据的响应
[PASS] 泄露的响应全部是 HTTP 200,只看状态码发现不了
[PASS] 只看状态码的测试全部通过(这正是问题所在)
[PASS] canary 测试能找出每一条泄露的响应
[PASS] 引擎在入口按 rejected 拦截后,不再泄露
[PASS] 池子不小于上下文长度时,拒绝路径根本走不到
[PASS] 启动时检查「KV 池容量 ≥ 上下文长度」能提前发现小池子配置
RESULT: 玩具模型中泄露只发生在「池子小于上下文 + 引擎只查 finished」的组合,状态码测试全过而 canary 测试全部抓到
python main.py 查看代码与内网复现步骤 →

来源

Esc
↑ ↓ 选择Enter 打开

分享图

1080 × 1350,适合发到群聊或朋友圈
分享图预览

键盘快捷键

j / k
下一条 / 上一条
o
展开或收起当前条目
Enter
打开当前条目详情
c
复制当前条目链接
s
收藏 / 取消收藏当前条目
/ 或 ⌘K
搜索
1 2 3
切换密度:标题 / 摘要 / 完整
t
切换主题
?
显示本帮助