不完整的修复:内存地址泄露在 vLLM 的新路由中卷土重来
vLLM 关键图像解析漏洞的修复对 OpenAI 路由做了净化处理,但数周后新增的路由仍会直接回显异常原文,泄露堆地址并重新打开一条绕过 ASLR 的原语。
这是什么?
2026 年 6 月 11 日,vLLM 项目发布了一则安全公告(GHSA-hgg8-fqqc-vfmw),由研究员 Kai Aizen(SnailSploit)报告。它记录了一次不完整的修复:此前用于修补 vLLM 兼容 OpenAI 路由中一处关键图像解析漏洞的补丁,并未扩展到稍后新增的路由,因此这些新入口仍会向远程调用方泄露内部内存地址。
原始漏洞相当严重——一个关键级(CVSS 9.8)漏洞,它把内存地址泄露与某图像库的堆溢出串联起来,最终实现远程代码执行。其修复引入了一个净化器,在错误消息抵达客户端之前,剥除对象表示中的地址。本次新发现被评为中危(CVSS 3.1 基础分 5.3),机密性影响较低,对完整性和可用性无影响。弱点类别为 CWE-532,即将敏感信息插入错误消息,与母漏洞属同一类别。受影响代码存在于直至 0.22.0(含)的各版本 vLLM 中。
它是如何工作的
当 vLLM 解析一张畸形图像时,图像库会抛出一个错误,其文本中包含缓冲区对象的内存表示——形如 cannot identify image file <_io.BytesIO object at 0x7a95e299e750>。末尾那个十六进制值是一个活动的堆地址。如果它原样传给客户端,攻击者便能得知进程地址空间中对象的位置,将 ASLR 熵从约四十亿种可能压缩到寥寥数个——这正是原始关键链条所依赖的侦察步骤。
母修复新增了一个 sanitize_message 辅助函数,并将其接入 OpenAI 路由的异常处理器,把 <_io.BytesIO object at 0x...> 改写为 <_io.BytesIO object>。问题在于,与该修复同期或之后新增的若干响应路径从未调用它。公告列出了五处这样的位置:兼容 Anthropic 的「messages」入口、其令牌计数入口、server-sent-events 流式转换器,以及实时语音识别 WebSocket 的两条错误路径。它们都把 str(exception) 直接返回给调用方。
一个自然的问题是:为什么 vLLM 那个全局的、会做净化的异常处理器没有拦下这些情形?答案在于一个值得内化的框架细节:全局异常处理器只对从路由中向外传播的、未被处理的异常触发。而每一条受影响的 HTTP 路由都在路由函数内部捕获异常并自行构建响应,因此净化处理器根本不会被调用。WebSocket 路径绕过它则出于另一个原因——WebSocket 帧根本不经过 HTTP 异常处理链。喂给母漏洞的那个畸形图像触发器,原封不动地抵达了所有这些新路由。
公告明确指出:这不是陈旧的遗留代码,而是一连串范围疏漏。净化器于 2026 年 1 月 9 日落地;Anthropic 路由在六天后新增却未纳入它,令牌计数入口约两个月后新增,语音识别路径则在五月新增——每一处都复刻了未净化的写法。
为什么重要
单看这条地址泄露,用户看不到任何变化。它的价值在于充当一块构件。母链条恰恰需要这条原语来击败 ASLR,随后才触发内存破坏。那第二阶段——某旧版图像编解码器中的堆溢出——已在库的较新版本中修复,因此在完全更新的技术栈上,本次发现只是一条信息泄露原语,而非通往代码执行的路径。但 vLLM 常被打包进自定义 Docker 镜像、下游重构建,以及固定了旧系统库的长生命周期 LTS 发行版。在任何仍搭载易受攻击图像编解码器的部署中,这些新入口都在悄悄重新激活初始补丁本应关闭的完整「先泄露、后破坏」链条。
更宏观的教训关乎修复如何衰减。在具体调用点应用的补丁只保护那些调用点。随着新路由、新传输方式和新入口不断加入,它们会重新引入修复本应消除的那种写法——除非缓解措施位于每条响应都必经的一个咽喉点。
防御
彻底的修复是升级到包含该项目修复 pull request 中所合并补救措施的 vLLM 版本。除升级外,公告的建议具有良好的普适性,并与 OWASP 关于敏感信息泄露的指南一致:
- 对称地净化错误输出。 任何向客户端返回异常文本的路径——HTTP 路由、流式转换器与 WebSocket 处理器——都必须清除对象表示与原始地址。只修一个路由,并不等于处处皆修。
- 将缓解措施移到咽喉点。 路由内部的
try/except块与 WebSocket 处理器会绕过框架级异常处理器。一个对所有出站错误体统一净化的响应中间件,可从根本上防止此类回归,让新增路由无法悄然重开泄露。 - 拓宽净化模式。 只匹配 CPython 那种精确小写地址后缀的正则表达式很脆弱;未来的运行时、C 扩展或自定义
__repr__方法都可能产生不匹配的格式。应剥除任何独立的十六进制地址,而非某一种特定形态。 - 绝不向不受信任的调用方返回原始内部错误。 详细异常在服务端记录;返回给客户端一个通用、不透明的错误。地址泄露、栈回溯和文件路径全都是侦察素材。
- 把不完整修复的后续排查视为头等要务。 修复关键漏洞时,先审查每一条同类路径和每一条新增路由是否存在相同的输出汇点,再宣布结案。
状态
| 项目 | 参考 | 日期 | 备注 |
|---|---|---|---|
| 后续公告发布 | GHSA-hgg8-fqqc-vfmw | 2026-06-11 | 信息泄露(CWE-532);CVSS 5.3 中危;未分配 CVE |
| 母漏洞 | CVE-2026-22778 / GHSA-4r2x-xpjr-7cvv | 2026 | 关键级(CVSS 9.8);泄露与堆溢出串联实现 RCE |
| 净化器引入 | vLLM PR #31987 | 2026-01-09 | 仅应用于 OpenAI 路由 |
| 受影响版本 | vLLM ≤ 0.22.0 | — | Anthropic 路由、令牌计数、SSE 转换器、语音 WebSocket |
| 修复 | vLLM PR #45119 | 2026 | 对遗漏位置应用净化 |
结论是一句老格言换了新场景:补丁的价值只等于它覆盖的面。把错误输出的净化收拢到每条响应都流经的单一节点,让原始内部状态远离面向客户端的消息;修复关键漏洞时,务必追查每一条共享其输出汇点的路由,再宣布其已关闭。
本文细节取自 vLLM 安全公告及所引用的 pull request。文中不复现任何概念验证载荷;防御者应查阅所链接的公告以评估自身暴露面。
Sources
- → https://github.com/vllm-project/vllm/security/advisories/GHSA-hgg8-fqqc-vfmw
- → https://github.com/vllm-project/vllm/security/advisories/GHSA-4r2x-xpjr-7cvv
- → https://nvd.nist.gov/vuln/detail/CVE-2026-22778
- → https://github.com/vllm-project/vllm/pull/45119
- → https://genai.owasp.org/llmrisk/llm022025-sensitive-information-disclosure/