TL;DR
- Brotli is Google's compression format, and a decoder is the code that turns a compressed br stream back into plain bytes; Node.js ships one inside
node:zlibso applications can decompress responses and request bodies without an extra dependency. - The upstream Brotli patch and vulnerable decoder source show how CVE-2026-111497 became an out-of-bounds write: an invalid block switch returned the temporary-input status, so streaming continued through an eight-byte internal buffer and wrote past its end.
- The CVE record places the flaw in Google Brotli 1.0.3 through 1.2.0 and names Brotli 1.2.1 as a fixed version; the Node.js advisory lists 26.x, 24.x and 22.x as affected and provides builds 26.12.1, 24.22.1 and 22.23.4.
- The CVE record describes crafted Brotli data from a remote unauthenticated attacker; OX Security's Node.js analysis traces untrusted data to the bundled decoder through
node:zlib, so a request body and a fetched response both arrive at the same code. - The CVE record scores it 9.2 under CVSS 4.0, with confidentiality, integrity and availability all rated high, and the Node.js advisory rates the issue high.
- The credit line names OpenAI Codex Security researchers, and the fix landed in the same release that carried dependency updates to c-ares, OpenSSL, SQLite, Undici and the CA bundle.
What the decoder did with an invalid block switch
Brotli streams data in blocks, and a block header carries a switch that tells the decoder how the next block is encoded. Malformed input can present a switch value the format does not allow. The correct response is to stop and report a format error, because no amount of additional input can make an invalid switch valid.
The Node.js 21 October 2026 security release page (nodejs.org/en/blog/vulnerability/october-2026-security-releases, retrieved 2026-10-24), where CVE-2026-111497 is listed as the fourth advisory in the release.
The google/brotli patch commit identifies the misclassification: an invalid block switch returned the same status as a temporary need for more input, allowing streaming to continue; the vulnerable decoder source defines the staging buffer as eight bytes. The streaming decoder therefore kept asking for bytes and appending them to an eight-byte internal buffer written for the case where a few more bytes would complete a header. That buffer is where the write ran past the allocation.
Google’s CVE Program record files it under two weakness classes: CWE-787, out-of-bounds write, and CWE-252, unchecked return value. The second one describes the shape of the bug more precisely than the first. A decoder that treats a permanent error as a temporary condition has effectively failed to check what its own parser told it, and the memory corruption follows from that.
Which Brotli and Node.js versions carry the flaw
Google’s CVE Program record names the affected range as Google Brotli 1.0.3 through 1.2.0 on all platforms, with three fixed versions: 1.0.10 on the old line, 1.1.1 and 1.2.1. Anyone maintaining a C build, a vendored copy or a language binding pinned to a Brotli release in that range is inside the affected window.
The CVE Program record for CVE-2026-111497 (cve.org/CVERecord?id=CVE-2026-111497, published 2026-10-22, retrieved 2026-10-24): CNA Google, out-of-bounds write in c/dec/decode.c.
Node.js ships its own copy, so the runtime has its own fixed builds. The advisory lists v26.12.1, v24.22.1 and v22.23.4, and states that the issue affects 26.x, 24.x and 22.x. Those builds provide upgrades for the three supported lines. The advisory also warns that end-of-life versions are affected and directs users to a current release.
Two details in the record make the upgrade harder to skip. The first is that the affected list is written as three ranges with a fixed version on each, which is the signature of a backport strategy: the 1.0 and 1.1 lines receive the same fix in versions 1.0.10 and 1.1.1. The second is that Node.js carries its own fixed builds on all three supported lines, so the runtime upgrade and the library upgrade can happen on the same schedule.
How an attacker reaches the decoder through a request body
The CVE record defines the general trigger, and the Node.js interface narrows it: an attacker who can supply Brotli data that an application decompresses with node:zlib can corrupt process memory. The condition covers unauthenticated delivery of crafted Brotli data to any application that invokes the decoder, including proxies, CDNs and other service types.
Netics visual built from the Node.js advisory and the CVE record (nodejs.org, cve.org, retrieved 2026-10-24): the exposure checks that follow from the advisory's trigger conditions.
Two paths carry attacker-controlled data into that function. A service that accepts request bodies compressed with Content-Encoding: br decodes data chosen by the caller. A service that fetches a URL a user supplies deals with the same exposure on the response side, because an HTTP client decodes the response before application code sees it. The decoder sits in the middle of both.
The practical inventory question follows from that. The practical inventory question is which services decode Brotli and which of them process data produced outside the service. A booking API that reads JSON bodies gets away with nothing if an upstream load balancer forwards br-encoded payloads, and a webhook receiver passes a third party's bytes straight into the runtime's decompressor.
What the CVSS 4.0 score of 9.2 measures
Google’s CVE Program record reports a CVSS 4.0 base score of 9.2, with the vector AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H. Read part by part, it says the attack travels over the network, needs no privileges and no user interaction, and that a successful attempt is rated high on confidentiality, integrity and availability. The AT:P term is the one worth noticing: an attack requires specific preconditions, which in practice means the target service has to decode the crafted stream.
The google/brotli v1.2.1 release page (github.com/google/brotli/releases/tag/v1.2.1, retrieved 2026-10-24), whose entire release body is the CVE-2026-111497 security note.
The public record leaves a material ambiguity: the CVE record labels the 9.2 score critical; Node.js rates the runtime issue high. When the precondition holds, the affected code sits in the request path of everything the process serves. Neither source explains the difference between those severity labels or quantifies exploitability across common Node.js deployment paths, which limits their value for patch triage.
Who found it and why that detail is on the record
The Node.js advisory credits OpenAI Codex Security, naming Khai Tran and Sylvie Mayer as reporters, with mcollina and aduh95 on the fix. The name lands in a month when automated vulnerability discovery has been the subject of several announcements. The advisory records the named researchers as the reporters and gives no discovery method.
Read carefully, the credit line describes people attached to a security team. The advisory leaves the discovery method unspecified. That restraint is worth matching: a decoder error-path bug of this shape is exactly the kind of thing a fuzzer or an analysis agent can surface, and it is also the kind of thing a careful reader of the format specification can find by hand.
The release card GitHub publishes for google/brotli v1.2.1 (github.com/google/brotli/releases/tag/v1.2.1, retrieved 2026-10-24): the security note as the release's only content.
What a Node.js estate should check and patch
Ten advisories landed in the same October release, and CVE-2026-111497 is one of them. The others cover DNS name truncation through NUL bytes, three separate TLS hostname verification issues, a keep-alive response mix-up, predictable crypto.randomUUID and randomInt values in snapshot builds, a zlib.ZipFile prefix leak, and two Permission Model filesystem bypasses. A single runtime upgrade clears all ten, which makes the patch decision easy and the timing question the only real one.
The exposure question outlives the upgrade. A service that decodes untrusted Brotli data has a decompression path that can fail in memory-unsafe ways, and that statement holds for the next decoder bug as well. Listing those paths, and knowing which of them accept third-party bytes, is the durable part of the response. A crash loop that nobody reads about is the failure mode here, and infrastructure monitoring with plain-language alerts is where that gap usually sits.
The PHP remote code execution patches involved a related patching decision: a widely deployed interpreter, a patch window measured in days, and services that had to decide whether to patch or to go offline. The Brotli case adds the compressed-body angle, which most estate inventories do not capture.
Originally published on the Netics blog.





Top comments (0)