Tiếng Việt

All vulnerabilities

The Brotli decoder writes past its buffer: the path matters more than the version

Node.js and Bun carry the Brotli decoder inside the program. A machine is reached only when br data passes through that decoder — from a stranger's request body, from another server's response, or from data the application decompresses itself. This page names the paths, which Brotli copy you run, and how to measure it.

High CVE-2026-111497

What happens

Google's Brotli decoder, versions 1.0.3 to 1.2.0, writes past its output buffer when it decodes a malformed stream incrementally. Fixed in 1.0.10, 1.1.1 and 1.2.1.

CISA added the flaw to its Known Exploited Vulnerabilities catalog on 2026-10-27, so it is no longer theoretical.

Node.js and Bun build Brotli in, so the fix arrives with the runtime release itself. Node.js 18, 20, 23 and 25 get no fix: those lines are out of support, and moving line is the only answer.

The path in

  • A request body with Content-Encoding: br. Express 5 with body-parser 2 decodes a request body from any client, unauthenticated. Express 4 with body-parser 1 answers 415 and never decodes. One Node server, two very different exposures — and the Node version number cannot tell them apart.
  • A br response from another server. fetch() decodes the response your application downloads. If the upstream is compromised or sends a malformed stream on purpose, the flaw happens on your side.
  • Decompression your own code calls. zlib.brotliDecompress or createBrotliDecompress on data you do not control.
  • Anything in front of Node. If a reverse proxy or CDN decodes br first, that layer's decoder is the one reached, and the Node version on the host says nothing about it.

Which Brotli

  • Built into the runtime: the build from nodejs.org or bun.sh. Upgrade the runtime, then restart the service.
  • Linked against the system library: Ubuntu's and Debian's nodejs package links libbrotli1. Patch with apt, then restart every process that maps it. Fixed: noble 1.1.0-2ubuntu0.1, resolute 1.2.0-3ubuntu0.1, trixie 1.1.0-2+deb13u1, bookworm 1.0.9-2+deb12u1.
  • Inside a container image: the application ships its own runtime. node -v on the host says nothing about it; measure inside the container, and the image must be rebuilt or re-pulled.

Running is not installed

  • After the upgrade the running process keeps the old copy until it restarts: /proc/<pid>/exe ends in (deleted), or /proc/<pid>/maps still lists libbrotli… (deleted).
  • So "patched" and "running the patch" are two different questions. A host that ran apt upgrade without restarting the service still decompresses with the vulnerable copy.

Affected and fixed versions

ProductCVEAffectedFixed in
Node.jsCVE-2026-11149722.x · 24.x · 26.x^22.23.4 · ^24.22.1 · ^26.12.1
BunCVE-2026-111497>=1.0.21 <1.4.41.4.4

Original description (Node.js · CVE-2026-111497): Node.js Brotli decoder out-of-bounds write permits remote code execution

Original description (Bun · CVE-2026-111497): Bundled brotli decoder has an out-of-bounds write (CVE-2026-111497)

What to do

  • Built-in copy: upgrade to Node.js 22.23.4, 24.22.1 or 26.12.1 (Bun 1.4.4), then restart the service.
  • System copy: upgrade libbrotli1 (or the whole package set), then restart every process that maps the library.
  • Image copy: rebuild the image on a fixed runtime, pull it, compose up -d, then measure the version inside the container.
  • If you cannot upgrade yet: block Content-Encoding: br at the proxy, and do not decompress br from a source you do not control.

Check yourself

node -v; bun -v

Tells you: the runtime on the machine

ldd $(command -v node) | grep -i brotli

Tells you: a libbrotli line means the system copy, so apt is the fix; no line means it is built in

npm ls express body-parser

Tells you: Express 5 with body-parser 2 is the br request-body path; Express 4 is not

dpkg -l libbrotli1

Tells you: the system library installed (Debian, Ubuntu)

ls -l /proc/$(pgrep -f 'node|bun' | head -1)/exe

Tells you: which file the process runs; (deleted) means the old one, after an upgrade

docker exec <container> node -v

Tells you: the version inside the image, not on the host

Sources

Written from the original advisory and the vendor's documentation; versions come from the site's data, updated 2026-11-10. Where they differ, the original advisory wins.