返回资讯中心
外部精选
软件工程
#开发者实时流

Broccoli2Shell: Brotli decoder RCE (CVE-2026-111497) in Node.js, Python and more

You're at risk if your code, or any library it uses, decompresses Brotli data that someone else controls. That happens in more places than you'd think, because HTTP clients decompress Brotli responses on their own.

Hacker News 最新theanonymousone2026/10/24 · 21 天前14 分钟阅读

以下正文同步自 Hacker News 最新,版权归原站所有,已转换为易读排版。

You're at risk if your code, or any library it uses, decompresses Brotli data that someone else controls. That happens in more places than you'd think, because HTTP clients decompress Brotli responses on their own.

Node's built-in fetch() decodes Content-Encoding: br responses automatically. So do Python's requests/urllib3 and aiohttp whenever a Brotli package is installed. Any server you talk to can send the payload, whether through webhooks, link previews, crawlers or "import from URL" features.

Express 5.0.0–5.3.0 and body-parser 2.0.0–2.3.0 inflate Brotli request bodies in parsers such as raw() and json(). Python frameworks and middleware that decode br bodies are exposed in the same way. A bare node:http server doesn't decode bodies by itself.

This means zlib.brotliDecompress*(), createBrotliDecompress(), brotli.decompress(), and any library that uses them on archives, caches or queue messages.

Express and body-parser don't contain the bug. They're just paths to it, so upgrading them won't help. Node.js bundles its own copy of Brotli, which means the system libbrotli doesn't matter there. Only the Node.js version does.

A Brotli stream is split into blocks, and the decoder switches between block types as it reads them. Before the fix, DecodeBlockTypeAndLength() in c/dec/decode.c returned a plain boolean, so callers couldn't tell a malformed stream from one that just needed more input. On the fast path, the decoder ignored the return value altogether.

A crafted stream can request a block switch that can't happen. The decoder took that to mean "need more input" and kept adding attacker bytes to an eight-byte internal buffer, writing past its end. The overwrite corrupts nearby decoder state. That's how a malformed stream can turn into a memory leak or code execution.

The upstream fix is google/brotli commit 0ed4268, along with 50a9b70, b418fa8 and da98063. It returns a hard format error, BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH (−17), to the caller. The bug is tracked as CWE-252 (unchecked return value) and CWE-787 (out-of-bounds write).

The PyPI packages Brotli and brotlicffi compile the same C decoder. Your code doesn't need to import them to be exposed. If either one is installed, these clients use it on their own:

Don't wait for your scanner. When this was disclosed, pip-audit, Dependabot and Safety didn't reliably flag the affected PyPI versions. The CVE record named the upstream Google repository, not the PyPI packages. GitHub's advisory now lists both packages (PYSEC-2026-4322 and PYSEC-2026-4323), but check by hand anyway.

If your bindings come from your Linux distribution (for example python3-brotli) and not from PyPI, the fix arrives through your distribution's security updates.

The bug is in Google's reference C decoder, not in Node.js or Python. Anything that ships or links Brotli 1.0.3 through 1.2.0 may be affected, even before an advisory names it.

Decoders rewritten in other languages aren't a concern. The Java, JavaScript and C# ports, which pdf.js, iText and HtmlUnit use, can't reach the bug. The Go port (andybalholm/brotli) had the same logic error, but it would only have crashed, and it was fixed on 23 October. Rust's brotli-decompressor catches the condition and returns an error. Code execution is only possible in the C decoder.

Many projects ship a private copy of the C decoder instead of using your system's library. A distribution update doesn't fix those: each project has to update its copy. We searched GitHub for vendored copies and read their headers on 24 October 2026. A copy is patched if it includes the new BLOCK_SWITCH error code.

Already fixed: Node.js, Bun, Chromium, Firefox, brotlicffi, ngx_brotli, Brotli4j, SumatraPDF, Ghostscript, CatBoost and YTsaurus, as well as Gentoo, Solus and VMware Photon packages.

This list isn't complete. GitHub's code search skips submodules and some very large repositories, and private or vendored-at-build-time copies don't show up at all. A project listed here may not reach the decoder in every configuration. If you maintain one of these projects, updating to 1.0.10, 1.1.1 or 1.2.1 (or cherry-picking commit 0ed4268) fixes it.

node --version

affected if below 22.23.4, 24.22.1 or 26.12.1, or on an end-of-life line

the Brotli version bundled into this Node binary

node -p "process.versions.brotli"

inside a container image

docker run --rm --entrypoint node <image> --version

Python

pip show Brotli brotlicffi

what pulls it in

pipdeptree -r -p Brotli

lockfiles

grep -i brotli poetry.lock uv.lock requirements*.txt Pipfile.lock 2>/dev/null

inside a container image

docker run --rm --entrypoint pip <image> show Brotli brotlicffi

System library

dpkg -l | grep -i brotli # Debian, Ubuntu rpm -qa | grep -i brotli # RHEL, Fedora apk info -v | grep -i brotli # Alpine

running processes that have the decoder loaded

sudo grep -l brotlidec /proc/*/maps 2>/dev/null

Check everywhere code runs: production, staging, CI runners, build images, serverless runtimes and developer laptops. Patch first any service that fetches URLs you don't control or accepts Content-Encoding: br bodies.

Node.js: through your version manager, base image or package source

nvm install 24.22.1 # or 22.23.4 / 26.12.1 FROM node:24.22.1-slim # Dockerfile

Python

pip install -U "Brotli>=1.2.1" "brotlicffi>=1.2.1.0"

then raise the constraint and regenerate poetry.lock / uv.lock / requirements.txt

Then restart every process, rebuild every image and redeploy. Update the pins in your lockfiles, or the next build will reinstall the vulnerable version.

Node.js has published no workaround. For Node.js, upgrading the runtime is the only complete fix.

正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。

打开原文
去社区讨论 →