
There is a memory corruption bug in Google's Brotli decoder, it is rated 9.2 critical under CVSS v4.0, and it affects every version from 1.0.3 through 1.2.0. Node.js disclosed it on 22 October as Node2Shell. Python shipped an advisory for the same flaw the next day, because the PyPI packages Brotli and brotlicffi compile the same decoder. If your stack speaks HTTP and decompresses responses, this one is probably in your dependency tree right now.
It cuts in both directions
A remote unauthenticated attacker sends a crafted Brotli-compressed stream and the decoder keeps accepting bytes it should have rejected. Those bytes overflow a small working buffer. Past that point the attacker can leak memory, crash the process, or take control of what runs. The uncomfortable part is that it works both ways: a malicious client can take over an unpatched server that accepts compressed request bodies, and a malicious server can take over an unpatched client that accepts compressed responses.
OpenAI found it in February and reported it as unauthenticated remote code execution. That date matters, and the reason it matters is not flattering to anyone.
The root cause is a boolean
The flaw lives in DecodeBlockTypeAndLength, the function that handles block switches, the points where a Brotli stream changes which Huffman tree it uses. In vulnerable versions it returns a plain boolean, and a false can mean two very different things. Either the stream is malformed, or the decoder needs more input. Callers cannot tell which. On the fast path, the decoder throws the return value away entirely.
A crafted stream can declare a single block type and then exhaust that block's length. That forces a switch which cannot succeed. The decoder then either reports that it needs more input for a stream that is already complete, or keeps decoding with the block state it had before. The second path is the out-of-bounds write.
The upstream fix, commit 0ed4268 in google/brotli, makes the function return an error code and adds a new one, BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH, which is minus seventeen. Decoding now stops on a format error on both the safe and the fast path. Diffing the 1.2.0 and 1.2.1 source releases shows the only meaningful change is that commit and a version bump.
So the fix has existed in source since February. What did not exist was a release. Brotli 1.2.1 is the first shipped version that carries it, which means every project that bundles Brotli had to wait, and every project that bundles Brotli has to ship its own update now.
Your scanner is blind to this one
You do not need to import Brotli for this to reach you. HTTP clients like requests, httpx and aiohttp load the package automatically when it is present. Aikido's writeup is blunt about the practical consequence: as of 23 October, advisory databases do not map this CVE to either PyPI package, so pip-audit, Dependabot and Safety will not flag vulnerable versions. You can run a clean scan and still be running 1.2.0.
Two more details worth keeping. Apache's mod_brotli does not decode Brotli, so that path is not affected. And flipping your Accept-Encoding header is not a fix, because a malicious server can send a Brotli response regardless of what the client advertises, and urllib3 picks its decoder from the response's Content-Encoding header, not from what you said you wanted.
What to actually do
Upgrade to Brotli 1.2.1, or brotlicffi 1.2.1.0, in every environment that has it. Then rebuild the container images that bundle it, because a lock file on a host does nothing for the layer already sitting in your registry. Redeploy, restart the services, and confirm the running workloads are on the patched build rather than assuming the pipeline did what you told it.
The part I keep coming back to is the gap between the fix and the release, not the bug. A memory corruption flaw in one of the most downloaded compression libraries on the internet was diagnosed correctly in February, fixed in source, and still reached the world as a critical advisory in October because nobody treated it as a security release. That gap is going to keep happening. It is also the reason nobody can give you the scanner report that says you are fine.