# Node 18 的服务被扫出 CVE-2026-111497，运维说这季度升不了，这个 Brotli 洞能先怎么挡？

**URL:** <https://www.shiqidu.com/t/topic/1816>\
**Category:** 开发调优\
**Tags:** Node.js, 信息安全\
**Created:** [2026 年10 月 27 日 11:47 UTC](https://www.shiqidu.com/t/topic/1816 "2026-10-27T11:47:01Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

作者： ![shiqidu\_editor](https://www.shiqidu.com/user_avatar/www.shiqidu.com/shiqidu_editor/32/528_2.png) [@shiqidu\_editor](https://www.shiqidu.com/u/shiqidu_editor)\
发布日期： [2026 年10 月 27 日 11:47 UTC](https://www.shiqidu.com/t/topic/1816/1 "2026-10-27T11:47:01Z")

</div>

安全扫描的工单挂到还在跑 Node 18 的服务上，编号 CVE-2026-111497，运维那边回得也很干脆：依赖太老，这个季度排不进升级窗口。可工单不会因为这句话自己关掉，至少得搞清楚这个洞打在哪，升级之前手上能做点什么。

这个编号是 Node 官方 10 月 21 日那批安全更新里的一条，问题出在 Node 自带的 Brotli 解码器。遇到结构不合法的压缩流，解码器没有直接报格式错误，而是当成输入还不够，继续等，结果一直往一个 8 字节的内部缓冲区里追加数据，写出了边界。官方写的后果是进程崩溃、泄露进程内存，或者远程代码执行，级别标的是 High。有些第三方通告按 critical 定级，给的分数也不统一，内部评级建议直接引 Node 官方公告：

> **[Node.js — Wednesday, October 21, 2026 Security Releases](https://nodejs.org/en/blog/vulnerability/october-2026-security-releases)**
>
> Node.js® is a free, open-source, cross-platform JavaScript runtime environment that lets developers create servers, web apps, command line tools and scripts.

官方这次只给 22、24、26 三条线出了补丁：

```plaintext
22.x -> 22.23.4
24.x -> 24.22.1 （注意是 24.22.1，停在 24.22.0 不算）
26.x -> 26.12.1

```

18 不在里面。官方的版本列表里 18、20、23、25 都已经是 EOL，公告也写了，每次安全发布时停止维护的版本一律视为受影响，所以别等 18 的补丁，不会有。版本列表：[https://nodejs.org/en/about/previous-releases](https://nodejs.org/en/about/previous-releases)

线上跑的是哪个版本，在进程所在的环境里看，容器就进容器看，别拿开发机的输出糊弄工单：

```bash
node -v
node -p "process.versions.node + ' / brotli ' + process.versions.brotli"

```

如果 node 是从发行版源装的，打包方可能自己回移补丁，这种情况要看发行版的安全公告，不能只看主版本号。

## 哪些地方会碰到

触发条件是应用去解压攻击者能控制的 Brotli 数据。光一个裸的 `http.createServer` 不会自己解请求体，要排查的是下面这些位置：

代码里直接对外部输入调 `zlib.brotliDecompress()` / `zlib.createBrotliDecompress()` 的，比如处理上传的压缩包、解第三方推过来的数据。

内置 `fetch()` 收到 `Content-Encoding: br` 的响应会自动解压。Akamai 的分析把这点单独拎了出来：只要你请求的上游是恶意的或者被攻破了，客户端这边就会被打。

用 Express 5 的也在范围里。Express 5 依赖 body-parser 2，body-parser 的 HISTORY 写着 brotli 支持是 2.0.0 加进来的，README 里 json / raw / text / urlencoded 几个解析器都会自动解 `br`，`inflate` 默认是 `true`。所以任何客户端发一个带 `Content-Encoding: br` 的请求体，默认就会被解压。Express 4 配的是 body-parser 1.x，按 HISTORY 看那条线没有 brotli，不过项目里如果自己装了 body-parser 2，一样要查。

文档：[GitHub - expressjs/body-parser: Node.js body parsing middleware · GitHub](https://github.com/expressjs/body-parser)

## 升级前先挡一挡

入口能控制的话，在网关直接拒掉带 br 编码的请求体，一般的业务接口很少需要收压缩过的请求体：

```nginx
# server 或 location 里
if ($http_content_encoding ~* "br") {
    return 415;
}

```

应用层再补一道，挂在所有 body 解析中间件前面。确定客户端不传压缩体的，干脆把 `inflate` 关掉，压缩请求体会直接被拒成 415。代价是 gzip 的请求体也一起被拒，有老客户端在传 gzip 的话先确认一下：

```js
app.use((req, res, next) => {
  const enc = String(req.headers['content-encoding'] || '').toLowerCase();
  if (enc.includes('br')) return res.status(415).end();
  next();
});

app.use(express.json({ inflate: false }));
app.use(express.urlencoded({ extended: false, inflate: false }));

```

出站这边，`fetch()` 能访问的目标收成白名单，再配合出口防火墙或安全组限制这台机器能连哪些地址。只改请求头里的 `Accept-Encoding` 没多大用，恶意服务器根本不会理你要什么编码。自己直接调 zlib 解 Brotli 的代码，能下线就下线，至少别再处理来源不明的数据。

这些都只是缓解，把已知的入口堵住，不等于漏洞没了。官方公告里没有给任何 workaround，要修掉只能迁到还在维护的版本线，并且至少是上面那三个补丁版本。18 直接跳 22 或 24 肯定有兼容性要处理，工单里可以先把网关和 `inflate` 的改动写上，同时把迁移排期定下来，别让这季度不升拖成一直不升。实在短期迁不动的，官方版本页上提到 EOL 版本可以通过 OpenJS 生态可持续计划的合作方买商业支持，这个就看公司愿不愿意掏钱了。

其他参考：

- 22.23.4 发布说明：[Node.js — Node.js 22.23.4 (LTS)](https://nodejs.org/en/blog/release/v22.23.4)
- 24.22.1 发布说明：[Node.js — Node.js 24.22.1 (LTS)](https://nodejs.org/en/blog/release/v24.22.1)
- 26.12.1 发布说明：[Node.js — Node.js 26.12.1 (Current)](https://nodejs.org/en/blog/release/v26.12.1)
- 新加坡 CSA 通告：[https://www.csa.gov.sg/alerts-and-advisories/alerts/al-2026-154/](https://www.csa.gov.sg/alerts-and-advisories/alerts/al-2026-154/)
- Akamai 技术分析：[https://www.akamai.com/blog/security-research/inside-node2shell-closer-look-cve-2026-111497](https://www.akamai.com/blog/security-research/inside-node2shell-closer-look-cve-2026-111497)

还卡在 18 上的，你们网关那层是怎么拦的？有没有遇到客户端真在传 br 请求体的情况？
