A memory-corruption bug in a decoder sounds like it affects everyone running the runtime. In practice, CVE-2026-111497 affects the subset of deployments that take compressed bytes from somewhere untrusted and expand them inside the Node.js process. Finding that subset is the whole task.

The defect in one paragraph

The Brotli decoder bundled with Node.js treats an invalid block switch as a request for more input instead of a permanent format error. A caller that keeps feeding bytes therefore keeps pushing data into an eight-byte internal buffer until it writes past the end of it. Because the write happens inside the decode path, an attacker who controls the compressed stream controls the bytes that land beyond the buffer. The advisory lists crash, disclosure of process memory and remote code execution as possible outcomes.

Paths that reach the decoder

Any code that calls the Brotli functions in node:zlib reaches it. In ordinary service code that usually means one of four shapes.

Compressed request bodies. A framework configured to accept Content-Encoding: br inflates the body before a handler sees it. The handler's authentication check runs after inflation, which is exactly the wrong order for this bug.

Compressed stored payloads. Job queues, caches and importers commonly store a compressed blob and expand it on read. If a producer outside the trust boundary can write that blob, the consumer inherits the defect.

Response inflation. A Node.js proxy, gateway or scraping worker that decompresses upstream responses puts third-party bytes through the same decoder.

File and archive handling. A CLI or upload processor that expands .br files supplied by users reaches the decoder without any network exposure at all.

Paths that do not

A service that only serves JSON, or that terminates Brotli at a reverse proxy written in another language, is not exposed through that route. Neither is a build pipeline that compresses artifacts for distribution but never decompresses untrusted input. This matters because it lets most of a large estate be closed as not reachable instead of sitting in a queue as unknown.

Turning a map into a test

Inventory is the first pass: find every process that imports the Brotli functions from node:zlib, directly or through a decompression middleware. Grep the code, then confirm against the running build, because the vulnerable code is in the runtime and a lockfile will not show it.

The second pass is a controlled negative test. Send a malformed Brotli body to a staging instance of each reachable endpoint and observe whether the decoder error surfaces as a handled format error. A process that crashes or produces an unexpected error code on malformed input deserves attention before anyone attempts a proof of concept.

The third pass is about blast radius. For each reachable path, ask what the process holds and whether it can be split. Moving inflation into a small worker with no database credentials converts a potential remote code execution into a crash that an orchestrator restarts.

Fixed releases

Upgrade to 22.23.4, 24.22.1 or 26.12.1 depending on the line in use, and stop treating end-of-life branches as supported. Where Brotli is vendored separately, the library floor is 1.0.10, 1.1.1 or 1.2.1, since the CVE record traces the defect to versions 1.0.3 through 1.2.0 in c/dec/decode.c.

The uncomfortable part

The vulnerability was found by Khai Tran and Sylvie Mayer of OpenAI Codex Security and fixed by mcollina and aduh95, which says something about how decoder bugs surface now. Most teams cannot reproduce that kind of review, so their defence is architectural: keep untrusted decompression small, isolated and behind an input ceiling. A thousand-line parser will eventually have a bad day; the design question is whether that day costs a process restart or a credential.

References