一个 Checkmk 扩展,用于在 Linux 主机上为每个 Brotli 解码器显示其是否受 Broccoli2Shell 影响——CVE-2026-111497,这是 Google 的 C 语言 Brotli 解码器中的一个越界写入漏洞,当程序解压来自不可信来源(HTTP 响应、请求体、归档文件)的 Brotli 数据时,可能导致远程代码执行。该漏洞于 2026-10-21/22 披露,并在 Brotli 1.0.10、1.1.1 和 1.2.1,Node.js 22.23.4、24.22.1 和 26.12.1,Python 包 Brotli 1.2.1 和 brotlicffi 1.2.1.0,以及 .NET 8.0.33、9.0.22 和 10.0.14 中修复。
它附带一个小型 POSIX shell 代理插件,仅收集事实(系统库 libbrotlidec、Node.js 二进制文件、Python Brotli 和 brotlicffi 安装、.NET 运行时、它们的版本、包变更日志、它们链接的对象、哪些进程加载了它们以及哪些仍在运行已被替换的版本)。这些事实意味着“已修复”还是“存在漏洞”,由 Checkmk 服务器上的检查插件决定,因此新信息——例如另一个已修复版本——只需更新 .mkp,而无需在每台主机上部署新脚本。
为什么不直接比较版本号: 各发行版会在不更改上游版本号的情况下回移植修复,并且它们会针对系统库构建 Node.js,而不是使用 Node.js 自带的副本。Debian 12 附带 libbrotli 1.0.9 和 Node.js 18.20.4(上游已停止维护,无修复)——两者均已修复,因为更新后的 libbrotli1 包才是 Node.js 实际运行所用的解码器。因此,该扩展会读取拥有每个解码器的包的变更日志,并沿着 Node.js 和 Python 扩展追踪到它们所链接的库。
cmk_addons.plugins 插件 API)。/proc/<pid>/maps)。使用 GNU 或 busybox 工具的纯 POSIX sh;包变更日志通过 dpkg、rpm 或 apk 读取。已在 Debian 系、Red Hat 系、Amazon Linux 和 Alpine 上测试,详见下文。| Checkmk 镜像 | 日期 | 结果 |
|---|---|---|
checkmk/check-mk-ultimate:2.5.0p17 | 2026-10-28 | 通过(构建、cmk-validate-plugins、冒烟测试、安装 + 发现 + 检查 + 代理烘焙) |
checkmk/check-mk-ultimate:3.0.0-2026.10.28(每日构建) | 2026-10-28 | 通过(构建、cmk-validate-plugins、冒烟测试、安装 + 发现 + 检查 + 代理烘焙) |
代理插件于 2026-10-28 针对各发行版自带的包和官方镜像运行(scripts/test_agent_plugin.sh),并加载了解码器的 node 和 python 进程。随后在磁盘上替换了库、node 二进制文件和 Python 扩展模块,重启检测报告了正在运行的进程。
发行版
| 发行版 | 解码器 | 插件结果 |
|---|---|---|
| Debian 12 | libbrotli 1.0.9-2+deb12u1、Node.js 18.20.4(链接)、python3-brotli | 已通过向后移植修复(changelog),Node.js 通过该库 |
| Debian 13 | libbrotli 1.1.0-2+deb13u1、Node.js 20.19.2(链接)、python3-brotli、python3-brotlicffi(链接) | 已通过向后移植修复,Node.js 和 brotlicffi 通过该库 |
| Ubuntu 24.04 | libbrotli 1.1.0-2ubuntu0.1、Node.js 18.19.1(链接)、python3-brotli、dotnet-runtime-8.0 8.0.32 | 已通过向后移植修复 - .NET 存在漏洞(8.0.33 尚未进入软件源) |
| AlmaLinux 8.10 | libbrotli 1.0.6-5.el8_10、Node.js 10.24.0(自带解码器)、python3-brotli | 库和 Brotli 已通过向后移植修复 - Node.js 10 存在漏洞(已停止维护,自带解码器) |
| AlmaLinux 9.8 | libbrotli 1.0.9-10.el9_8.1、Node.js 16.20.2(链接)、python3-brotli、dotnet-runtime-8.0 8.0.32 | 已通过向后移植修复 - .NET 存在漏洞 |
| AlmaLinux 10.2 | libbrotli 1.1.0-8.el10_2.1、Node.js 22.23.2(链接)、python3-brotli | 已通过向后移植修复 |
| Fedora 44 | libbrotli 1.2.1、Node.js 22.23.1(链接)、python3-brotli 1.2.1 | 已通过版本修复 |
| Amazon Linux 2023 | libbrotli 1.1.0-1.amzn2023.0.1、Node.js 18.20.8(链接) | 存在漏洞 - 尚无修复包,Node.js 通过该库 |
| Alpine 3.22 | brotli-libs 1.1.1、Node.js 22.23.4(链接)、py3-brotli 1.1.1 | 已通过版本修复 |
官方镜像与 PyPI
| 镜像 | 解码器 | 插件结果 |
|---|---|---|
node:24.22.0-slim | Node.js 24.22.0(自带解码器) | 存在漏洞 |
node:24.22.1-slim | Node.js 24.22.1(自带解码器) | 已通过版本修复 |
node:20-alpine | Node.js 20.20.2(自带解码器) | 存在漏洞 - 已停止维护,无修复 |
node:24.22.0-slim,二进制文件移至 /home/dev/.nvm/...(归某用户所有) | Node.js 24.22.0 | 存在漏洞 - 版本从二进制文件读取,而非运行 |
python:3.12-slim + pip install Brotli==1.2.0 brotlicffi==1.2.0.0,/srv/app/venv 中的 venv 带有 Brotli 1.1.0 | Brotli、brotlicffi(自带解码器) | 存在漏洞(通过其运行进程发现该 venv) |
python:3.12-slim + 当前 PyPI | Brotli 1.2.1、brotlicffi 1.2.1.0 | 已通过版本修复 |
mcr.microsoft.com/dotnet/runtime:8.0.32 / :8.0 | .NET 8.0.32 / 8.0.33 | 存在漏洞 / 已通过版本修复 |
Checkmk 站点本身(2.5.0p17)的 Python 中不附带 Brotli 包。该插件尚未在容器之外的生产主机上运行过 - 尤其是在启用 SELinux 强制模式(RHEL 系列)的情况下;在该环境中,代理通常以非受限模式运行。
Setup > Maintenance > Extension packages > Upload package,或在站点内使用命令行:
mkp add broccoli2shell-<version>.mkp
mkp enable broccoli2shell <version>
将 agent 插件部署到要检查的主机:
在主机上运行服务发现。每个解码器都会获得自己的服务,另外每台主机还会获得一个
Broccoli2Shell restart 服务。
可选:在 Setup > Services > Service monitoring rules > Broccoli2Shell (CVE-2026-111497) 和 Broccoli2Shell restart 中调整状态。
将 package/agents/plugins/broccoli2shell 复制到 agent 插件目录的
cache-interval 子目录中,并使其可执行:
install -m 755 broccoli2shell /usr/lib/check_mk_agent/plugins/3600/broccoli2shell
3600 目录会让 agent 每小时在后台运行一次,并在两次运行之间提供缓存结果。不要把它直接放进 plugins/:它会读取大型二进制文件以及每个进程的内存映射,这对每次 agent 查询来说负担过重。
| 服务 | 每个 | 状态(默认,可配置) |
|---|---|---|
Broccoli2Shell <path> | 解码器,例如 Broccoli2Shell /usr/lib/x86_64-linux-gnu/libbrotlidec.so.1、Broccoli2Shell /usr/bin/node、Broccoli2Shell /usr/lib/python3/dist-packages (brotli)、Broccoli2Shell /usr/lib/dotnet (.NET 8.0) | OK 已修复或不受影响 - CRIT 存在漏洞,且被运行中的进程加载 - CRIT 存在漏洞,但未被加载 - UNKNOWN 无法确定版本或链接的库 |
Broccoli2Shell restart | 带有解码器的主机 | OK - CRIT 进程仍在使用已被替换的解码器 |
这些截图来自一个 Checkmk 2.5.0p17 测试站点,其四台主机使用 sample-data/ 中的录制数据代替真实 agent(没有真实主机):Debian 12 和 Ubuntu 24.04 通过向后移植修复,Node.js 通过系统库修复,但 Ubuntu 上的 .NET 8.0.32 仍存在漏洞;Amazon Linux 2023 的库尚未修复,因此其 Node.js 也未修复;还有一个使用来自 PyPI 的 Brotli 和 brotlicffi 的 Python 应用。它们都仍有进程在运行已被替换的解码器。

服务详情会指明下一步、相关软件包、其变更日志内容以及它所链接的库:

flowchart TD
A[Decoder] --> L{"Linked against the<br/>system libbrotlidec?"}
L -- "yes (distribution Node.js,<br/>Debian's brotlicffi)" --> LIB[result of that library's service]
L -- "not found" --> U[UNKNOWN]
L -- no --> B{Version known?}
B -- no --> U
B -- yes --> C{"Version >= fix of its branch?<br/>libbrotli/Brotli 1.0.10 / 1.1.1 / 1.2.1<br/>brotlicffi 1.2.1.0<br/>Node.js 22.23.4 / 24.22.1 / 26.12.1<br/>.NET 8.0.33 / 9.0.22 / 10.0.14<br/>or a newer branch"}
C -- yes --> OK[OK: fixed]
C -- no --> D{"Package changelog names<br/>CVE-2026-111497?"}
D -- yes --> OKB[OK: fixed by distribution backport]
D -- no --> E{"Loaded by a running process?"}
E -- yes --> CR[CRIT: vulnerable]
E -- no --> CR2["CRIT: vulnerable<br/>(own state in the rule)"]
--shared-brotli 构建(通过 libnode.so 或直接链接),Debian 还将 brotlicffi 针对系统库构建。它们的服务显示该库的结果,并指向该库对应的服务。官方 Node.js 构建和 PyPI wheel 自带解码器;Node.js 24.22.1 在 process.versions.brotli 中仍报告 Brotli 1.2.0,因为 Node.js 修补了其捆绑副本——在那里只有 Node.js 版本起作用。Content-Encoding: br 请求体,卸载 Python 包以使 urllib3、requests 和 aiohttp 回退到 gzip/deflate)位于解码器之外。服务输出始终会指明下一步操作。