Prompt Cache 作为隐蔽信道:TTFT 探测泄露跨租户 Prompt
提示词缓存(Prompt caching)是一种只要开启就能立即获益的优化手段。长系统提示词仅需哈希一次,KV 状态驻留在 GPU 显存中,随后任何复用该前缀的请求都能跳过预填充(prefill)成本。供应商报告称,对于缓存的请求,延迟降低了 80%,输入成本降低了 90%。在大规模应用中,这种经济效益是无法抗拒的:摊销到数百万次调用中的单一共享前缀,将一项支出变成了几乎可以忽略不计的尾差。
实现这种节省的机制本质上是一种共享资源,其命中或未命中的状态可以通过延迟来观察。这种可观察性就是侧信道(side channel)。在网络外部可以清晰分辨缓存命中与缓存未命中,这种差异巨大且具有确定性。这项在成本看板上占有一席之地的优化方案,还兼任了一份无人预料的工作:泄露同一供应商下其他租户当前正在进行的活动信息。
有趣的地方并不在于有人可能会利用这一点,而在于这个侧信道是该优化方案的结构性特征,而非漏洞——将其修复至零意味着必须放弃节省成本所依赖的缓存复用。大多数生产团队尚未就这种权衡进行过明确的讨论。成本看板说 一套,威胁模型(如果提到缓存的话)说的是另一套。连接这两者之间的桥梁本该进行安全评审,但实际上并没有。
TTFT 如何成为侧信道
其原理非常直接,且计算方式是公开的。当一个请求到达启用了前缀缓存的推理服务器时,运行时会哈希提示词的前导块,并在内存中已有的 KV 状态中进行查找。命中意味着预填充可以直接跳至后缀部分;首标记时间(TTFT)从数百毫秒降至数十毫秒。未命中则意味着模型需要从头开始重新计算前缀。延迟差异巨大、可重复且可以通过普通 HTTP 连接从网络客户端进行测量。
如果攻击者怀疑另一个租户正在使用特定的前缀,他们会发送该候选前缀并记录响应时间。较短的 TTFT 意味着前缀匹配了已缓存的内容,这证明了另一个主体最近提交了一个前缀重叠的请求。通过重复探测、变换候选内容,缓存就变成了一个“是或否”的预言机(oracle),可以回答“是否有人在这里提交过以 X 开头的请求”。
2024 年的论文 The Early Bird Catches the Leak 表明这并非理论。研究人员在七家商用 API 供应商中检测到了跨组织的全局缓存共享,并使用增量搜索算法,以 92.3% 的准确率逐个标记(token-by-token)恢复了系统提示词,平均每个标记仅需 234 次查询。I Know What You Asked (NDSS 2025) 展示了仅通过 TTFT 测量,针对 vLLM 和 SGLang 多租户部署进行的端到端提示词重构。Auditing Prompt Caching in Language Model APIs 对主要供应商的公共 API 进行了统计假设检验,检测到了与供应商自身文档相矛盾的每用户、每组织以及全局缓存行为。攻击研究的发展速度极快,以至于大多数防御文献都落后了一个周期。
攻击者获得的能力并非“解密跨租户数据”,而更接近于“向缓存询问关于其他租户最近发送了什么的‘是或否’问题”。这种能力足以恢复运营商认为保密的系统提示词,确认竞争对手是否正在运行前缀匹配猜想的工作流,或者识别 SaaS 功能用于引导模型的上下文示例。所有这些都不需要攻破模型,只需要缓存的命中或未命中状态是可观察的,而这正是其设计使然。
优化通过共享资源耦合了租户
看待这个问题的最清晰方式是意识到,前缀缓存是一种“多租户原语”(multi-tenancy primitive),就像共享的 CDN 缓存或共享的数据库连接池一样。一旦属于其中一个租户的状态影响了另一个租户观察到的延迟,这两个租户就不再是隔离的了。这就是耦合。耦合是这项优化的核心——它是节省成本的来源——同时也是租户审查本该标记出来的风险点。
这里的成本与安全权衡比大多数情况都要尖锐。如果你对缓存进行分区,使任何两个租户都不能共享数据块,侧信道就会关闭。但命中率也会随之崩塌——每个租户在每个新前缀上都要支付全额的预填充成本。供应商之所以将提示词缓存作为一项功能开发,正是因为共享前缀(系统提示词、工具 schema、few-shot 示例)在数百万次客户调用中不断重复。让缓存具有存在价值的资产,恰恰也是导致其泄露的资产。目前还没有明显的手段能让你 在获得完全共享带来的成本节省的同时,兼顾完全分区带来的隔离性。
供应商实际采取的做法是选择一种粒度。Anthropic 和 OpenAI 现在将缓存复用的范围限制在组织级别:同一组织内的请求可以复用彼此缓存的前缀,但禁用了跨组织共享。Anthropic 的文档明确表示缓存条目在组织之间是隔离的。OpenAI 在 2024 年的信息披露后也做了类似更改,现在声明缓存是“在组织级别隔离的,不在账户之间共享”。Azure OpenAI 的文档也描述了同样的立场。这些变化发生在研究人员在同样的 API 上演示了跨租户泄露之后,而此前这些供应商的文档一直声称这些 API 是安全的。披露周期的运作方式一如既往:当有人发布漏洞利用程序时,威胁模型才会更新。
在单个组织内部,缓存仍然是共享的。对于许多企业来说(一个组织即为一个信任边界),这是可以接受的;但对于 SaaS 供应商来说,这并不可接受,因为他们自己的客户是其运行在推理供应商之上的应用程序的租户。如果你的产品将客户复用到单个推理供应商组织中,那么你的客户之间就在共享缓存,而供应商提供的组织级隔离并不能给你提供每客户的隔离。你必须自己构建隔离机制。
“自行构建”的具体实践
vLLM 项目一直在公开推进这一工作,其贡献者们展现的设计空间是生产团队在阅读该主题时最有用的参考产物。RFC #16016 建议在请求中增加 cache_salt 字段,并将其注入到第一个 KV 块的哈希中,这样即使两个请求的文本前缀完全相同,只要 salt 不同,就无法共享缓存状态。PR #17045 实现了该设计的单屏障版本,并在 vLLM 的稳定版本中发布。
- https://arxiv.org/html/2409.20002v1
- https://arxiv.org/abs/2502.07776
- https://arxiv.org/abs/2508.08438
- https://arxiv.org/html/2508.09442v1
- https://www.ndss-symposium.org/wp-content/uploads/2025-1772-paper.pdf
- https://github.com/vllm-project/vllm/issues/16016
- https://github.com/vllm-project/vllm/pull/17045
- https://docs.vllm.ai/en/stable/design/prefix_caching/
- https://platform.claude.com/docs/en/build-with-claude/prompt-caching
- https://developers.openai.com/api/docs/guides/prompt-caching
- https://learn.microsoft.com/en-us/answers/questions/2117496/how-does-azure-openai-ensure-prompt-caching-privac
- https://developer.nvidia.com/blog/structuring-applications-to-secure-the-kv-cache/
- https://aisecurityhandbook.com/chapter-3/prompt-leakage-kv-cache-sharing.html
- https://www.schneier.com/blog/archives/2026/02/side-channel-attacks-against-llms.html
