OpenAI Found a Brotli Flaw That Can Own Your Node.js Server

OpenAI Found a Brotli Flaw That Can Own Your Node.js Server

Here is a nightmare that started with a spell-checker's worst enemy: a file compressor. This week, OpenAI's red team — the people paid to break things — announced they had found a way to seize control of servers through Brotli, the humble compression library quietly bundled into Node.js, Bun, and Envoy. No password. No login. Just a carefully poisoned package of compressed data.

It has a name already, because every serious bug apparently needs branding now: Node2Shell. And the twist that makes this story genuinely unnerving isn't the exploit itself. It's that the fix has been sitting in Brotli's source code since February. For eight months, everyone treated it as routine maintenance. Nobody thought to call it what it was: a skeleton key.

We checked the CVE record, the Node.js advisory listing and Imperva's technical write-up end to end before writing this, and confirmed the CVE still has no entry in CISA's known-exploited catalogue. Everything below is attributed to the sources named at the foot of the article.

Rows of server racks in a data centre, representing the kind of machines running Node.js behind the web

Photo: Server racks at the NERSC data centre. The flaw lives in the compression layer beneath applications running on machines like these — file photo, CC0 1.0 via Wikimedia Commons.

The bug that hid in plain sight for eight months

Start with the timeline, because it is the most damning part of the story. On February 27 this year, a change landed in the Brotli repository — the upstream Google project — that corrected how the decoder handles a malformed stream. It shipped with no release, no advisory, no fanfare. Somebody fixed a memory-safety bug and nobody realised it was a security fix.

Then, on October 21, Node.js released 22.23.4, 24.22.1 and 26.12.1 — part of a security release covering ten CVEs — and listed CVE-2026-111497 as an out-of-bounds write in its bundled Brotli decoder that "permits remote code execution." Node.js rated it High; the CVE record, filed by Google as the assigning authority, carries a CVSS 4.0 score of 9.2 — critical, a number that sends security teams scrambling on a Friday afternoon.

Which raises the obvious, uncomfortable question: how does a critical remote-code-execution primitive get fixed in February and only identified as critical in October? The answer is botched triage — the industry's polite word for nobody reading the commit with a security mindset. Compression libraries are the plumbing of the internet; nobody inspects the pipes until the basement floods.

The discovery is credited to OpenAI's Codex Security team — researchers Khai Tran and Sylvie Mayer — who reported it to the Node.js project. Node.js's own advisory, as quoted by Imperva, credits Matteo Collina with reporting it and Antoine du Hamel with landing the fix. However the credit divides, the point stands: it took OpenAI's red team, hunting for trouble on purpose, to notice what the ecosystem had walked past for eight months.

How a compressed file becomes a shell

Brotli is a compression format — Google's, designed to make web pages load faster. The decoder is the half that unpacks compressed data back into something readable. In Node.js it is reachable two ways, and both are bad: when a server's middleware inflates a Brotli-compressed request body from a client, and when an application uses Node's built-in fetch() to read a Brotli-compressed response from some other server. Untrusted data, either direction, reaches the same native decoder.

The attack is cruelly simple in concept. The malicious stream declares the block types it will use, then performs a block switch that the stream's own structure rules out — an impossible transition. The vulnerable decoder misreads that as a request for more input and keeps going in an invalid internal state. Imperva's sanitizer run showed what happens next: it writes past its intended buffer, an out-of-bounds write. Once an attacker can scribble outside the lines like that, running their own code is, as one analyst put it, often the next stop.

The patched decoder just stops with a format error instead of continuing. That's it. That was the February change.

From a weakened build to the real thing

Here's where sceptics had a point — briefly. The first public proof of concept only crashed the process on a standard build; code execution had only been shown on a deliberately weakened test binary. Fair enough: crashing a server is a nuisance, not a takeover.

Then Imperva's Red Team, led by researcher Ron Masas, published its analysis on October 22 and killed the scepticism. In fresh containers running the official, unmodified Node.js 24.22.0 Linux arm64 image — no debugger, no custom build — their standalone proof of concept ran attacker-supplied code carried in a Brotli request or response body. The proof that it worked was humble and old-school: a marker file that wasn't supposed to exist simply appeared. The test application had no code to create that file; the code carried in the Brotli data had run inside the target process.

As Swati Khandelwal wrote for The Hacker News: "Malicious Brotli data can make an application on an official build of Node.js run attacker-supplied code, security researchers at Imperva have demonstrated."

Imperva reproduced execution through both routes: the response path via fetch(), and the inbound path through Express 5.0.0–5.3.0 and body-parser 2.0.0–2.3.0, whose parsers now decode Brotli request bodies by default. (For the record: a bare Node.js HTTP server doesn't decode incoming Brotli just by receiving it, and Express 4-era setups reject such bodies with a 415 error — the middleware is a route into the flaw, not its source.) On the patched 24.22.1, the same inputs were rejected before any code could run. The proof was also non-deterministic — it took multiple attempts — and Imperva only verified Linux arm64, not the x86-64 machines that fill most data centres. But the memory bug is the same everywhere, so nobody should take comfort in that.

No login. Two ways in. Every version that matters.

Let's stack up what makes this one genuinely alarming, not just scary-sounding. The attack is unauthenticated — no credentials, no account, no session. It works in both directions: a malicious client can attack an unpatched server by sending poisoned compressed data, and a malicious server can attack an unpatched client that accepts compressed responses. And it hits every supported Node.js line — 22.x, 24.x and 26.x — because the flaw is in the bundled decoder, not in any one application.

The affected range in the CVE record is Google's Brotli 1.0.3 through 1.2.0, fixed in 1.0.10, 1.1.1 and 1.2.1. But the blast radius is bigger than Node.js: Bun shipped its update in 1.4.4, and Envoy bundles the same library — which is exactly why OpenAI's disclosure told every project shipping Brotli to update, not just the Node.js crowd. If you're still on Node.js 20.x or earlier, there is no cavalry coming: those lines are end-of-life and will never receive the fix.

The same-day response was encouraging, at least from the big platforms. Vercel, which runs Node.js for its customers, said it added firewall rules on October 21 that block the attack in inbound requests. But — and this is the part people keep missing — those rules don't cover Brotli responses your application fetches from other servers, and they don't replace patching. An edge rule on inbound traffic does nothing for the fetch() call your code makes to a third-party API. Only upgrading the runtime removes the flaw, and the advisory offers no temporary workaround inside Node.js itself.

Close-up of server hardware with status lights in a server room

Photo: Server racks at the NOIRLab headquarters computer room in Tucson, Arizona. A package inventory can miss an older Node runtime bundled inside a container image — file photo, CC BY 4.0 NOIRLab/NSF/AURA/T. Slovinský via Wikimedia Commons.

The AI irony nobody should miss

There is a delicious, slightly terrifying symmetry to this story. OpenAI — the company whose models are routinely accused of writing insecure code — found this one the old-fashioned way: a red team, hunting deliberately. And the exploit was then proven by a different set of humans, with a memory sanitizer and patience. Imperva's closing analysis names the trend outright: "AI can accelerate both vulnerability discovery and exploit development, helping researchers investigate flaws while lowering the time and effort attackers need to turn those flaws into working attacks. For defenders, that means less room to delay between disclosure and remediation."

Less room to delay. Remember that line. Because Imperva's own analysis draws a straight line from Node2Shell to the AI-discovered PHP2Shell flaw we covered this week — researchers used AI assistance to uncover and exploit longstanding memory-safety bugs there too. "Different engine, different failure mode, same uncomfortable reminder," wrote security analyst Anaz Haidhar, "safe-looking application code still depends on native code underneath it."

That is the pattern, and Anthropic's security chief warned us about exactly this acceleration this week: AI is compressing the time between a bug existing and a bug being weaponised. Brotli's eight-month snooze happened during the quiet era. The next one won't get that luxury.

Our verdict: eight months is colossal

Let's say the quiet part plainly. A 9.2-rated, unauthenticated, bidirectional remote-code-execution flaw in one of the most-deployed compression libraries on earth was fixed in February and not flagged as a security issue until October. That is not an attacker outsmarting defenders. That is the ecosystem staring at the fix and shrugging.

And yet — credit where it's due — once found, the response was swift: patches in the disclosure window, same-day WAF rules, and an honest write-up. Compare that with the PAN-OS zero-day panic that rattled Palo Alto's stock this month, and the industry's reflexes are visibly improving.

But the deeper lesson is the one AI makes unavoidable. The gap between "bug exists" and "bug weaponised" is shrinking — Imperva said it, and Node2Shell proved it twice over. The plumbing era of security — where a fix could sit unflagged for eight months without consequence — is over. The attackers won't wait, and neither can the patch schedule.

What to do before Monday

  • Patch Node.js to 22.23.4, 24.22.1 or 26.12.1 (or newer) — including inside container images. A Dockerfile pinned to node:24.22.0 stays vulnerable no matter how often you rebuild it.
  • Update Bun to 1.4.4 and check anything else bundling Brotli 1.0.3–1.2.0 — Envoy included.
  • Prioritise services that decompress data they don't control — outbound fetch() calls to third-party APIs first, then request-body parsers.
  • If you can't upgrade immediately, reject Content-Encoding: br request bodies at the edge as a stopgap — but it covers only the inbound path.
  • On unsupported Node.js lines (20.x and earlier): move to a supported release. No fix is coming.

As of this writing, no exploitation in the wild has been publicly confirmed — but with a working proof of concept in the open, "not yet" is doing a lot of heavy lifting in that sentence.

Update, Oct. 24: it runs on the official build — and the blast radius is bigger than Node

The proof of concept hardened fast. Imperva researchers demonstrated arbitrary code execution on the official Node.js 24.22.0 Docker image for Linux arm64 — no debugger, no deliberately weakened build — by feeding crafted data to the bundled Brotli decoder, The Hacker News reported on October 23. It took several attempts, and the same data was rejected outright on the fixed 24.22.1 release. As of October 22, no in-the-wild exploitation had been reported, and the CVE was not in CISA's Known Exploited Vulnerabilities catalog (Security Boulevard).

The blast radius also widened past Node.js. Aikido's follow-up analysis — now calling it 'HTTP2Shell' — found the same out-of-bounds write in Google Brotli 1.0.3 through 1.2.0 on all platforms, and warned that Python stacks are exposed too: urllib3, requests, httpx and aiohttp automatically load brotli or brotlicffi when either is present, so any Python app calling an untrusted server can decode a poisoned stream. As of October 23, Aikido said, pip-audit, Dependabot and Safety did not flag the vulnerable PyPI packages — the fixes are Brotli 1.2.1 and brotlicffi 1.2.1.0. One small mercy: Apache's standard mod_brotli does not decode Brotli, so it is unaffected.

The timing is worth noting: the flaw was found by OpenAI's Codex Security team in the same week the company published its DNS-escape post-mortem and locked frontier training offline — OpenAI's models are finding the holes now. Occasionally, they have also been the ones walking through them.

FAQ

What is CVE-2026-111497 (Node2Shell)?

An out-of-bounds write in the Brotli decoder bundled with Node.js that permits unauthenticated remote code execution. CVSS 4.0: 9.2 (Critical) in the CVE record.

Which versions are affected?

Node.js 22.x, 24.x and 26.x before 22.23.4, 24.22.1 and 26.12.1. The underlying bug is in Google Brotli 1.0.3 through 1.2.0.

Does a WAF fully protect me?

Only partly. Vercel's rules (Oct 21) and Imperva's rules block the inbound path; they don't cover Brotli responses your app fetches, and they don't replace upgrading.

Is Node2Shell being exploited in the wild?

No public confirmation as of this writing; the CVE is not in CISA's Known Exploited Vulnerabilities catalogue, though a public proof of concept exists.

Am I affected if I never use Brotli directly?

Possibly. Exposure needs two things: a runtime below the fixed version, and attacker-controlled data reaching the decoder. In Express 5 and body-parser 2.x, json(), urlencoded(), text() and raw() all decode Brotli request bodies — as do the Koa body parsers and @fastify/compress. The built-in fetch() decodes Brotli responses, so code fetching user-supplied URLs is exposed too. Express 4 and body-parser 1.x do not decode Brotli request bodies. (Security Boulevard)

Does Node2Shell affect Python too?

Yes. Google Brotli 1.0.3–1.2.0 is vulnerable on all platforms, and urllib3, requests, httpx and aiohttp automatically load brotli or brotlicffi when installed — so a Python app calling an untrusted server can decode a poisoned stream. Upgrade to Brotli 1.2.1 or brotlicffi 1.2.1.0. As of October 23, pip-audit, Dependabot and Safety did not flag the vulnerable packages. (Aikido)

Sources

Reporting: Imperva Red Team's "Node2Shell" analysis (Oct 22, 2026); The Hacker News, Oct 23, 2026 (both Node2Shell pieces); PANews and CryptoBriefing relays of OpenAI's Oct 23 X disclosure; SocPrime's CVE-2026-111497 analysis; SecurityBoulevard; Anaz Haidhar's Node.js Brotli RCE write-up. Internal coverage: AI Found 'PHP2Shell', Anthropic's Security Chief Warns 18 Months of Cyber Hell, Palo Alto Shed 18% as a Zero-Day Met AI's Debt Panic.


Daniel Rao is a senior technology writer for TechPulse USA, covering cybersecurity, AI infrastructure and the software supply chain.

Comments

Popular posts from this blog

Nous Research Raises $90M With Trump Jr. Firm on Cap Table

Nadella Says Assume Every AI Model Is Already Compromised

Firmus axes $5.5B IPO after 'greedy' A$44B valuation revolt