CVE-2026-111497:Node.js Brotli 越界写可致 RCE

2026 年 10 月 21 日,Node.js 发布三个受支持分支的安全更新,修复 10 个漏洞,其中 4 个为高危。最严重的是 CVE-2026-111497:内置 Brotli 解码器存在越界写,官方描述为「可导致远程代码执行」。修复版本为 22.23.4、24.22.1、26.12.1,已停止维护的 20.x 及更早分支不再提供补丁。

事件概述

Brotli 是 Google 推出的 HTTP 压缩格式,在同等压缩率下比 gzip 更省带宽,主流浏览器普遍在 Accept-Encoding: br 中声明支持。Node.js 通过 node:zlib 内置了 Brotli 解码能力,只要进程解压了攻击者可控的 Brotli 数据,就落在影响面内。

技术细节

官方未给出触发条件与利用细节。第三方分析指出,修复方式是从上游 Brotli 挑拣提交 0ed4268a,让解码器在遇到「流中声明只有一种块类型、却出现块切换」的畸形数据时立即失败。缺陷由 Node.js TSC 主席 Matteo Collina 报告,Antoine du Hamel 修复。

暴露路径三条:

  • 直接调用 node:zlib 的 Brotli 解压接口处理不可信数据;
  • 使用 fetch() 请求返回 Brotli 压缩响应的外部地址;
  • body-parser 一类自动解压请求体的中间件。

同批另外三个高危都在证书与域名校验上:CVE-2026-105483 在用全角数字书写 IP 地址时绕过 TLS 主机名校验(仅 24.x、26.x);CVE-2026-106069 在主机名松散解析为 IP 时校验失效;CVE-2026-105482 使 dns.resolve 遇空字节截断域名,导致查询名与实际解析名不一致。三者都能让客户端接受非目标站点的证书,中间人风险上升。

中危项有一条值得记住:CVE-2026-106074,crypto.randomUUID() 与 randomInt() 的熵缓存在启动快照与单可执行文件(SEA)打包时被写进镜像,每个进程会重复生成同一批随机值。低危项则是 ZIP 头校验失败后返回攻击者字节(CVE-2026-106070,仅 26.x)与 Permission Model 绕过。

影响评估

Node.js 未给这 10 个漏洞发布 CVSS 分数,仅标 High。Vercel 公告更进一步,称研究者在其未修补版本上「演示了进程内存泄露与命令执行」,但这属 Vercel 表述,不是 Node.js 官方结论。截至 10 月 22 日无在野利用报告;同日公开的 PoC 仅在刻意弱化的测试构建上取得代码执行,标准构建上作者只看到崩溃与有限的进程内存读取。

修复建议

node --version   # 应为 v22.23.4 / v24.22.1 / v26.12.1

# Dockerfile
FROM node:22.23.4-slim
docker build --pull --no-cache -t app:patched .
  • 逐台核对服务器、构建机、CI 镜像里的 Node 版本;Docker 基础镜像自带一份运行时,需重建而非只改依赖。
  • Debian/Ubuntu 包链接系统 libbrotli,不在 Node 内置副本内,须等发行版 brotli 包更新;截至 10 月 21 日 Debian 安全跟踪器尚无该 CVE 条目。
  • 20.x 及更早已 EOL,必须迁移到受支持分支,不存在补丁。
  • 同批还更新根证书(NSS 3.131.1)剔除 eMudhra 中间 CA 受影响链,一次升级可同时解决证书侧问题。

参考来源