CVE-2026-9678CVE-2026-9678是Undici HTTP客户端缓存拦截器中存在的一个缓存投毒漏洞。Undici是Node.js生态系统中最常用的HTTP客户端库之一,其缓存拦截器(cache interceptor)用于缓存HTTP响应以提高性能。该漏洞存在于Undici的缓存拦截器对Cache-Control响应头的解析逻辑中。当上游服务器返回使用空白字符填充的限定性private或no-cache字段名时,例如`private=" authorization"`或`no-cache="\tauthorization"`,Undici的解析器会保留字段名周围的空白字符,导致后续与字面量"authorization"字段名的比较失败,从而使本应标记为不可缓存的响应被错误地存储到缓存中。在共享缓存模式下,这一缺陷可能导致包含某个用户认证数据的响应被从缓存中提供给后续请求者,包括未经认证的请求者,前提是两个请求解析到相同的缓存键。受影响的应用程序需要满足以下条件:显式启用了缓存拦截器(interceptors.cache())的共享模式、向上游转发Authorization头、且接收到具有非规范的限定性private或no-cache指令的可缓存响应。该漏洞的CVSS评分为5.9,属于中危级别,主要影响机密性(C:H),对完整性和可用性无影响。
该漏洞的核心问题在于Undici缓存拦截器对HTTP Cache-Control头部字段的解析逻辑缺陷。具体技术原理如下:
1. **HTTP缓存控制规范**:根据RFC 7234,Cache-Control头部的private和no-cache指令可以接受字段名参数,用于指定哪些响应头字段不应被缓存或不应被共享缓存存储。例如,`Cache-Control: private="Authorization"`表示包含Authorization头的响应不应被共享缓存存储。
2. **解析缺陷**:Undici的缓存拦截器在解析这些限定性指令时,没有正确地修剪(trim)字段名参数周围的空白字符。当上游服务器返回类似`private=" authorization"`(authorization前有空格)或`no-cache="\tauthorization"`(authorization前有制表符)的头部时,解析器会保留这些空白字符。
3. **比较失败**:由于解析后的字段名包含空白字符(如`" authorization"`而非`"authorization"`),后续与字面量"authorization"的字符串比较将失败。这意味着系统错误地认为该指令没有指定Authorization字段,从而将本应标记为不可缓存的响应视为可缓存。
4. **缓存投毒利用**:在共享缓存模式下,攻击者可以通过以下方式利用此漏洞:
- 第一步:合法用户发送带有Authorization头的认证请求,获取包含敏感数据的响应;
- 第二步:该响应被错误地缓存(因为Cache-Control的private指令未被正确识别);
- 第三步:攻击者(可能未认证)发送相同缓存键的请求,从缓存中获取其他用户的认证数据。
5. **利用条件**:需要满足三个条件——启用共享缓存模式、转发Authorization头、且上游返回非规范格式的Cache-Control头。
修复版本v7.28.0和v8.5.0中,开发者在解析Cache-Control字段名参数时添加了trim操作,确保空白字符被正确处理。