A Brotli Flaw Found by OpenAI Codex Security Forced Patches in Node.js, .NET and Python, and Vendors Rate It From Medium to Critical
The fix reached Brotli’s source on February 27, 236 days before a release carried it, and Google, Microsoft, Red Hat and Ubuntu now rate the same bug differently.
Microsoft published out-of-band fixes on Sunday, October 25 for CVE-2026-111497, an out-of-bounds write in Google’s Brotli decompression library, and its advisory covers .NET, Visual Studio and PowerShell. Node.js and the two Python Brotli packages had already shipped fixed releases, and OpenAI’s advisory lists fixed Bun, Envoy and Istio builds as well. Google published Brotli 1.0.10, 1.1.1 and 1.2.1 on October 21. OpenAI Codex Security found the bug. The change that fixes it is older than any of the advisories: it was committed to Brotli’s source on February 27 under the title “Detect and report invalid stream earlier,” 236 days before a release carried it.
Table Of Content
Outlets call the flaw Node2Shell, Broccoli2Shell or HTTP2Shell. None of the sources we read reports attacks in the wild, and CISA’s Known Exploited Vulnerabilities catalog, whose latest release is dated October 23, does not list the CVE. What the vendors disagree on is how bad it is: Google scores it 9.2 and critical, Node.js calls it high, Red Hat important, Ubuntu medium, and Microsoft files it under elevation of privilege. For defenders the more useful question is where untrusted Brotli data reaches a decoder, and whether that decoder is a copy an operating system update will not touch.
We read the CVE record, the NVD entry and the GitHub advisory; the Node.js advisory; OpenAI’s Patch the Planet advisory and its post on X; Imperva’s write-up; Microsoft’s Security Update Guide entry and its GitHub announcement; the upstream fix commit; the Ubuntu, Debian and Red Hat trackers; and coverage by BleepingComputer, SecurityWeek and The Register. We also ran one local test of Python HTTP clients. We did not fetch, run or link any exploit code.
What the flaw is
Google’s CVE record describes “a buffer overflow vulnerability in the Brotli decoder (c/dec/decode.c)” in Brotli 1.0.3 through 1.2.0 that lets a remote, unauthenticated attacker use a crafted Brotli stream to corrupt adjacent decoder memory, disclose memory contents, cause a denial of service, or potentially execute code. It lists two weakness types, CWE-787 (out-of-bounds write) and CWE-252 (unchecked return value). The Node.js advisory gives the mechanism: “An invalid block switch was reported as a temporary need for more input instead of a permanent format error, so the streaming decoder kept appending input bytes to an eight-byte internal buffer.”
The upstream change is small enough to read in the diff. DecodeBlockTypeAndLength() used to return a boolean, and the old code returned false both for an impossible block switch and when it simply needed more input, so a caller could not tell them apart. The commit makes the function return a decoder error code and adds BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH (value -17), so an impossible block switch now ends decoding with a format error.
The fix was in Brotli’s source for 236 days
The fixing commit, 0ed4268, landed in google/brotli on Friday, February 27 with that generic title. The latest release at the time, 1.2.0, was four months old (published October 27, 2025), and the next releases were the ones Google published on October 21 with a security note naming the CVE. OpenAI’s account of the gap: “This root cause issue was actually fixed in the Brotli source code in February, but it wasn’t known at the time that it gave rise to a security vulnerability and there was no more recent release of Brotli.”
Source and releases therefore told different stories for almost eight months. Alan Coopersmith noted on oss-security that Ghostscript appears to have pulled the commit into its bundled copy for 10.07.1rc1, so some projects were fixed without knowing it. Anything pinned to a released Brotli, including the Node.js builds and the PyPI wheels, was not. A scanner that matches on version numbers had no advisory to match until October.
| When (UTC) | What happened | Record |
|---|---|---|
| Oct 27, 2025 | Brotli 1.2.0 published, the last release before the fix | GitHub releases |
| Feb 27, 2026, 13:10 | Commit 0ed4268, “Detect and report invalid stream earlier.”, lands in google/brotli | GitHub commit |
| Oct 16, 09:58 | Google reserves the CVE ID | CVE record |
| Oct 20 and 21 | Node.js 22.23.4 and 24.22.1 (dated Oct 20) and 26.12.1 (Oct 21) appear in Node’s download index; the advisory is dated Oct 21 | nodejs.org |
| Oct 21, 19:26 to 19:27 | Brotli 1.0.10, 1.1.1 and 1.2.1 published | GitHub releases |
| Oct 22, 13:35 to 16:19 | CVE record published (13:35); PyPI Brotli 1.2.1 uploaded (13:57); NVD entry (14:17); GitHub advisory (15:32); brotlicffi 1.2.1.0 uploaded (16:19) | CVE.org, PyPI, NVD, GitHub |
| Oct 23 | OpenAI’s advisory updated; GitHub marks its advisory reviewed (19:08); OpenAI posts on X (22:55); OSV’s PyPI records carry this date | OpenAI, GitHub, OSV |
| Oct 25 (Sunday) | Microsoft publishes its entry and fixed .NET 8.0.33, 9.0.22, 10.0.14 and 11 RC 3 | MSRC, GitHub |
One CVE, seven ratings
| Source | Rating | What it rests on |
|---|---|---|
| Google, in the CVE record | 9.2, critical (CVSS 4.0) | Network, low complexity, no privileges, high impact on confidentiality, integrity and availability; attack requirements present (AT:P) |
| Node.js | High | Heading of its October 21 entry for the bundled decoder |
| Microsoft | CVSS 3.1 8.1 base, 7.1 temporal; Critical for .NET and Visual Studio, Important for PowerShell; impact Elevation of Privilege | AC:H; publicly disclosed yes, exploited no, “Exploitation More Likely” |
| Red Hat | Important, CVSS 3.1 8.1 | Attack complexity scored high; “no public, reliable remote code execution proof-of-concept” |
| Ubuntu | Medium | Priority in its CVE tracker |
| CISA, SSVC entry in the CVE record (Oct 23) | Exploitation none; automatable no; technical impact total | Decision points, not a severity score |
| NVD | Awaiting Analysis | Shows only Google’s CVSS 4.0 score |
Two scoring choices explain most of the spread. Google’s CVSS 4.0 vector rates attack complexity low and records the extra conditions as an attack requirement. Red Hat says it reads that requirement as high attack complexity, which makes the bug “Important rather than Critical,” and Microsoft’s CVSS 3.1 vector also uses AC:H, so the two reach the same 8.1.
Microsoft’s impact label is the outlier. Its entry reads “Out-of-bounds write in .NET allows an unauthorized attacker to elevate privileges over a network,” and its release data files every product it lists, 19 entries across .NET 8 to 11 on three operating systems, four Visual Studio builds and three PowerShell versions, under Elevation of Privilege. Its GitHub announcement lists the possible outcomes as “information disclosure, denial of service, or elevation of privilege.” Node.js and OpenAI say remote code execution. Anyone who triages by impact type will land in different queues depending on which advisory they read.
Who decodes Brotli decides who is exposed
- Node.js. The advisory says an attacker who can supply Brotli data that an application decompresses with
node:zlibcan corrupt process memory. Imperva says it reached code execution on the official Node.js 24.22.0 Linux arm64 image through a Brotli response read by the built-infetch()and through request bodies parsed by Express 5 and body-parser 2 (tested at Express 5.0.0 and 5.3.0 and body-parser 2.0.0 and 2.3.0, with the releases in between untested), and that 24.22.1 rejected the same inputs. It adds that “A bare Node.js HTTP server does not decode incoming Brotli bodies simply by receiving them.” - .NET. Microsoft’s entry says “Brotli decompression is not enabled by default in an out-of-the-box .NET or ASP.NET Core install.” Applications are exposed through ASP.NET Core request decompression,
HttpClientautomatic response decompression, or direct use ofBrotliStreamorBrotliDecoder. Microsoft says .NET Framework is not affected. - Python. The PyPI packages Brotli and brotlicffi compile the same decoder. We tested Python 3.13.14 on Windows against a local server that returned plain bodies:
requests2.34.2 (with urllib3 2.8.0) andhttpx0.28.1 both sentAccept-Encoding: gzip, deflate, brwhen the fixed Brotli 1.2.1 wheel was installed, andgzip, deflatewhen no Brotli package was present. So these clients advertise Brotli only when a binding is installed (we tested thebrotliwheel, not brotlicffi), but OpenAI’s advisory cautions that “Removing br from Accept-Encoding alone does not stop a server from sending it.” - Other paths. Harry Sintonen wrote on oss-security on October 26 that git’s HTTPS remote helper is also vulnerable when libcurl is built with Brotli support. The Register reports that JFrog built an exploit path through FFmpeg and libjxl, which reads Brotli-compressed metadata inside JPEG XL images, so file parsing is in scope as well as HTTP. OpenAI’s advisory adds Envoy and Istio gateways with a Brotli decompressor filter, and Electron apps, where a fixed Chromium does not fix the embedded Node.js runtime.
The split between system and bundled copies matters for patch planning. Ubuntu’s tracker marks its nodejs package not affected because it “uses system brotli,” so the fix reaches that package through brotli. The official Node.js binaries carry their own decoder, and the Broccoli2Shell tracker, as BleepingComputer relays, warns that updating the system library does not fix Node.js deployments or other applications that bundle their own copy.
Is it exploitable? The sources disagree
- OpenAI calls it a vulnerability “that allows for unauthenticated remote code execution in Brotli.”
- Imperva says its proof of concept worked on the tested Linux arm64 setups but “did not succeed on every attempt,” and that execution took multiple attempts. SecurityWeek says Imperva has not made its exploit public.
- SecurityWeek reports that a public proof of concept on GitHub reportedly achieves code execution only against an intentionally weakened build, and that some researchers argue the bug can only cause a denial of service. We did not fetch or run any proof of concept.
- Red Hat says there is “no public, reliable remote code execution proof-of-concept,” and that ASLR, non-executable memory, FORTIFY_SOURCE and SELinux make reliable code execution harder without eliminating crashes.
- Microsoft records the flaw as publicly disclosed and not exploited, with “Exploitation More Likely.” CISA’s SSVC entry reads exploitation none, automatable no, technical impact total.
The sources agree that a crash or a memory disclosure is possible when untrusted Brotli data reaches a vulnerable decoder. They disagree about how reliably that becomes code execution, and nothing we read shows it happening against a real target.
Where the coverage and the records differ
- The name. BleepingComputer’s headline calls it HTTP2Shell, yet its text says “the vulnerability is not specific to HTTP/2.”
- The credit. Imperva’s post says the Node.js advisory “credits Matteo Collina with reporting it and Antoine du Hamel with the fix.” The advisory credits Khai Tran and Sylvie Mayer of OpenAI Codex Security with reporting it, and the GitHub handles mcollina and aduh95 with the fix. The CVE record also lists OpenAI Codex Security as the finder.
- The dates. BleepingComputer says the PyPI packages with the fixes “became available on October 23.” PyPI’s upload times are October 22, 13:57 UTC for Brotli 1.2.1 and 16:19 UTC for brotlicffi 1.2.1.0. The October 23 date matches OSV’s advisory records.
- The 9.2. The Broccoli2Shell site says “Rated 9.2 Critical (CVSS 4.0) by GitHub.” The score originates in Google’s CVE record, which the GitHub advisory repeats.
What is still unpatched
- Distributions. Ubuntu’s tracker marks the
brotlipackage fixed for jammy, noble, resolute and stonking, and still “needs-triage” for xenial, bionic and focal. Debian’s tracker shows fixes in the bookworm (DLA-4855-1) and trixie (DSA-6582-1) security updates and in unstable, with forky still vulnerable. Red Hat rates the CVE Important and listsistio-proxyin OpenShift Service Mesh 3 among the affected products. - Bundled copies. The Broccoli2Shell tracker lists DuckDB, Apache Arrow, 7-Zip-zstd, p7zip, v8-jsi, EDK II and woff2 as unpatched and says its list is incomplete. We checked five of the linked threads on October 26: the DuckDB and Arrow pull requests are open and unmerged, and the 7-Zip-zstd, EDK II and woff2 issues are open.
- Old Node.js lines. The tracker says Node.js 25, 23, 20 and older get no fix because they are end of life. Node.js’s own advisory covers 22, 24 and 26.
- Scanners. The CVE record lists affected versions of Google’s Brotli library and does not name the PyPI packages. The PyPI wheels were uploaded on October 22, GitHub marked its advisory reviewed at 19:08 UTC on October 23, about 29 hours after the first upload, and OSV’s records for the two PyPI packages are dated October 23. PyPI’s JSON for Brotli 1.2.0 now carries both PYSEC-2026-4322 and the GitHub advisory, and brotlicffi 1.2.0.0 carries PYSEC-2026-4323. Our pip-audit and SBOM tutorial shows how to check what a scanner skips.
What to do now
- Update, then restart and rebuild. Fixed releases are Node.js 22.23.4, 24.22.1 and 26.12.1; Python Brotli 1.2.1 and brotlicffi 1.2.1.0; Brotli library 1.0.10, 1.1.1 and 1.2.1; Bun 1.4.4; and .NET 8.0.33, 9.0.22, 10.0.14 and 11 RC 3. Microsoft’s release data lists Visual Studio 16.11.61, 17.14.43 and 18.11.2. Running processes keep the old decoder, so restart every service and rebuild every container image that embeds an affected runtime.
- Find the decode paths. Run
node --versioninside each image, andpython -m pip show Brotli brotlicffiin each Python environment. In .NET code, search forAddRequestDecompression,AutomaticDecompression,BrotliStreamandBrotliDecoder, the three paths Microsoft names. - If patching must wait, reject
Content-Encoding: brbefore any proxy or parser decompresses it, and turn off automatic Brotli decoding in HTTP clients. OpenAI’s advisory includes examples for Express, Envoy and Istio, and urllib3, and warns that “Request-size limits and WAF rules alone do not cover every decoding path.”
OpenAI’s Patch the Planet site, which it calls an OpenAI Daybreak initiative, lists two recent disclosures: this one and the PHP flaws we covered in our PHP2Shell patch report. It says every finding is reviewed by a person and that maintainers stay in control of their code and releases. For another AI lab’s reports landing in a widely used C project, see curl’s record 24-flaw release, which included a high-severity bug reported by Anthropic.
We fetched the records between about 19:10 and 19:30 UTC on October 26. NVD’s entry was last modified at 18:17 UTC and still read Awaiting Analysis, and CISA’s feed was still the October 23 release. Microsoft’s details come from its Security Update Guide API record, its release data and its GitHub announcement. We ran no exploit, fetched no proof-of-concept code and generated no Brotli data; the Python test used a local server that returned plain text. We contacted none of the organizations. The Register’s account of JFrog’s FFmpeg work and the Broccoli2Shell tracker’s lists are reported as theirs, and we checked only the five threads named above.








No Comment! Be the first one.