HTTP2Shell: The Bread Roll That Overflowed Its Buffer

By Jag Journey, LLC Guest Author
Oct 26, 2026 8 min read 550 views
HTTP2Shell: The Bread Roll That Overflowed Its Buffer
A flaw in Google's Brotli decompressor, nicknamed HTTP2Shell, turned out to live far beyond Node.js: inside .NET, FFmpeg, ClickHouse and more. What it is, what we fixed on October 26, and a checklist for your own stack, with bread puns.
Share:

Brotli is a compression format from Google. Its name means "small bread roll" in Swiss German, which is honestly adorable. This week the small bread roll learned how to write past the edge of its own plate, and half the internet spent Monday checking its pantry.

The bug is CVE-2026-111497. Security researchers have given it a few nicknames, including Node2Shell and HTTP2Shell, because nothing says "please patch me" like a name that sounds like a heavy metal album. It lives in Brotli's decoder, the part that unpacks compressed data. Almost everyone borrowed that decoder, so the bug turned up in a lot of places at once.

Here is what it is, what we fixed on Monday, October 26, and a checklist you can run on your own systems. There will be bread puns. We kneaded them.

What HTTP2Shell actually is #

When a Brotli decoder unpacks data, it follows little instructions such as "the next chunk is a different kind of chunk." In the affected versions, a malformed instruction could look exactly like a polite "I need more input, please." The decoder said "no problem," carried on with its internal bookkeeping in a mess, and wrote data past the end of a small working buffer.

In plain English, the decoder mistook "this is broken" for "feed me more." We have all worked with someone like that. Writing past the end of a buffer is how programs crash on a good day, and how attackers sneak in their own code on a bad one. Programmers call it an off-by-one error. This one was more of an off-by-a-lot.

The affected versions are Brotli 1.0.3 through 1.2.0. The fixed releases are 1.0.10, 1.1.1 and 1.2.1. Google, which assigned the CVE, scores it 9.2 out of 10. Red Hat rates it Important, at 8.1. Either way, this is a "patch it this week" bug, not a "we will get to it after the holidays" bug.

Why it showed up everywhere at once #

The first fixes arrived in the Node.js security releases on October 21. If the story ended there, this would be a very short post. It did not. On October 25, researchers at JFrog showed the same flaw reaching far past Node.js, because many projects do not use the operating system's copy of Brotli. They pack their own copy inside the app, like a sandwich brought from home.

  • .NET carries its own Brotli inside the runtime. Its Brotli streams, HttpClient's automatic decompression and ASP.NET Core's request decompression all use it. Microsoft shipped out-of-band fixes on October 25: .NET 8.0.33, 9.0.22 and 10.0.14.

  • FFmpeg could reach the bug through JPEG XL images, which can carry Brotli-compressed metadata. One crafted picture is enough, and no web traffic is involved at all.

  • ClickHouse crashed when it was sent a crafted Brotli-compressed request.

  • Apache Arrow got stuck in an endless loop on a 534-byte input. That is not memory corruption, just a processor running laps forever, which is its own special kind of Monday.

  • Python's Brotli and brotlicffi packages, the Bun runtime, Envoy proxies, curl builds and Linux distribution packages were in the blast radius too.

The lesson: checking your Node.js version and calling it a day is like testing one smoke detector in a house with twelve rooms.

Three ways the bread gets in #

  1. The front door. Someone sends your server a request with the header Content-Encoding: br, and a server that unpacks it before checking who is asking swallows the bad bytes whole.

  2. The back door. Your own app fetches a URL, perhaps a webhook, a link preview or an import, and a hostile server replies with a Brotli body. Many HTTP clients unpack whatever the reply says it is, even if you never asked for Brotli. Taking br out of your Accept-Encoding header does not save you, because the server gets the last word.

  3. The mail slot. Files: images, archives, fonts and data files with Brotli tucked inside. No HTTP is involved, so no firewall sees them coming.

As of the latest public reports, nobody had seen the bug used in a real attack, and it was not on CISA's list of known exploited vulnerabilities. One security team did report running its own code on an unmodified Node.js build in a lab, so "nobody has seen it yet" is a head start, not a hall pass.

What we did on Monday #

We run our own servers for our products and for the sites our customers trust us with, so we went looking for every copy of the bread roll, including the ones baked into apps.

  • We checked the whole pantry. Every server and every runtime, the system library, Node.js, .NET, Python packages, our app build machines and the containers our build pipelines use, including the copies apps carry inside themselves.

  • We locked the front door. None of our services needs to accept Brotli-compressed request bodies, so our web servers now answer them with HTTP 415, "Unsupported Media Type." That is the web's polite way of saying "we don't do that here." Our edge network blocks them before they ever reach us.

  • We rebuilt the Swift Warning backend. The service behind our wildfire alert app carries its own copy of .NET, so updating the server underneath it would have changed nothing. It now runs on .NET 10.0.14, and its build refuses to ship anything older. The phone and desktop apps pick up the fixed runtime in their next release.

  • We rounded up the strays. A leftover Node.js install moved to 24.22.1, and the machines that build our apps got Microsoft's patched .NET SDKs.

  • We hired a robot. Some Linux distributions have not published their fixed packages yet. A small scheduled job now checks every hour, installs the fix the moment it appears, restarts the services that use the library and posts in our team chat. If the fix is slow to arrive, the robot starts nagging us every day, which it is extremely good at.

A checklist for your own stack #

  1. Find every copy, not just the obvious one. Check your operating system's package, then everything that brings its own: Node.js, Bun, .NET apps (self-contained ones especially), Python virtual environments, media tools and data engines.

  2. Update to the fixed versions. Node.js 22.23.4, 24.22.1 or 26.12.1. .NET 8.0.33, 9.0.22 or 10.0.14. Python Brotli 1.2.1 or brotlicffi 1.2.1.0. Bun 1.4.4. Brotli itself 1.0.10, 1.1.1 or 1.2.1. Distribution packages as your vendor ships them.

  3. Rebuild anything that packs its own lunch. Self-contained .NET apps, compiled Bun executables and container images keep the old decoder until you rebuild them. Updating the server underneath them does nothing.

  4. Restart things. A running process keeps the old library loaded until it restarts, like a party guest who did not hear the party ended. "Have you tried turning it off and on again?" remains the oldest security patch in IT, and it is still undefeated.

  5. Close the front door if you can. If nothing you run needs Brotli-compressed request bodies, reject them at your proxy or firewall. Browsers do not send them, so your visitors will never notice.

  6. Mind the back door until you are patched. Code that fetches URLs other people choose should not automatically unpack Brotli on an unpatched runtime. In .NET that means leaving Brotli out of HttpClient's automatic decompression for those calls.

  7. Check what is actually running. Confirm the version your live process reports, not the version your config file promises. Config files are optimists.

Questions we expect, answered with a straight face #

Is HTTP2Shell a bug in HTTP/2? #

No. Despite the name, the flaw is in the Brotli decompressor, not in the HTTP/2 protocol. It can be reached through web traffic that uses Brotli compression, and through files that contain Brotli data.

Do I need to do anything if I use Jag Journey apps or host a site with us? #

No. We handled it on our side, and our robot installs the last vendor patches the moment they ship. Our apps pick up the patched runtime in their next update, so keep automatic updates on.

Why does every bug get a catchy name now? #

Because "CVE-2026-111497" does not fit on a T-shirt.

The bottom line #

HTTP2Shell is a good reminder that modern software is a potluck. Everyone brings a dish, and sometimes three dishes share the same bad ingredient. We found our copies, closed the doors we do not use, rebuilt the app that packs its own lunch, and put a robot on watch for the last patches. If you run your own servers, the checklist above should get you most of the way there in an afternoon, with time left over for a sandwich. Make it a bagel. Bagels are not compressed with Brotli.

Sources #

J

Jag Journey, LLC

The team behind Swift Warning, VoVo and the rest of the Jag Journey family of apps.

Comments (0)

Sign in or sign up to comment.

No comments yet. Be the first to share your thoughts!