Creuto is now an OpenAI Select Partner Read More
You can block Brotli requests nginx-side to buy time on CVE-2026-111497, but the rule covers inbound traffic only — every outbound fetch() stays exposed.

Node.js published no workaround for CVE-2026-111497. Not a flag, not a config toggle, not a supported way to turn the Brotli decoder off — the advisory names the reporter and the fixer and stops. So if you cannot upgrade a service today, your only lever is to block Brotli requests nginx-side, and you should know before you ship that rule that it closes one of the two ways in.
Here is the rule, the equivalents on the platforms most teams actually run, and the path that stays open regardless.
The bug is an out-of-bounds write in the Brotli decoder Node.js bundles, rated High and fixed in 22.23.4, 24.22.1 and 26.12.1. The decoder is reachable from node:zlib, so there is no middleware setting that disables it and nothing to feature-flag. You are left with keeping the hostile bytes away from the process.
That makes this a reverse-proxy problem by elimination rather than by design, which is worth saying plainly — a mitigation you picked because nothing else exists deserves more scepticism than one the vendor recommends.
Match the request's Content-Encoding and refuse it before proxy_pass. Using map rather than a bare if keeps the test out of the request-processing path where if inside location has well-known surprises:
map $http_content_encoding $brotli_body {
default 0;
"~*\bbr\b" 1;
}
server {
location / {
if ($brotli_body) {
return 415;
}
proxy_pass http://app_upstream;
}
}
Three details matter. The word-boundary match catches br inside a list such as gzip, br, which a plain equality test against "br" misses. 415 Unsupported Media Type is the honest status — the server understood the request and refuses that encoding — and it is easier to spot in logs than a 400. And because this is a request header, it has nothing to do with Accept-Encoding: you are not turning off Brotli responses to clients, and compression on the way out is unaffected.
Verify it before you trust it. Send a request that declares the encoding and confirm the proxy refuses it rather than passing it along:
curl -i -X POST https://your-host/api/anything \
-H 'Content-Encoding: br' \
--data-binary @/dev/null
A 415 means the rule is live on that path. A 200, or anything that looks like your own application's error page, means the request reached the app — most often because the rule sits in a different server block than the one serving that route, or because a layer in front rewrote the header set before your config saw it. Test every public hostname, not just the one in your notes.
If you run ingress-nginx rather than nginx directly, check whether snippet annotations are permitted in your cluster before you plan around one; many clusters disable them, and the rule then belongs in the controller's ConfigMap or in a gateway in front of it.
Watch your cache keys while you do this. If a layer in front of nginx varies on request headers, a newly rejected encoding can land a 415 in a shared cache entry — the same class of problem as getting the HTTP Vary header wrong on personalised pages.
| Layer | What to do | Caveat |
|---|---|---|
| nginx / ingress | Reject Content-Encoding: br, return 415 | Applies per server block — check every vhost |
| Cloudflare | WAF custom rule on the request header, action Block | Runs before cache; confirm it is on the right zone and not in log-only mode |
| AWS ALB | No header-value condition on listener rules; use WAF | Listener rules match host, path and method — a WAF web ACL is the place for this |
| Vercel | Nothing to do inbound | Rules were added on 21 October, automatically, at no cost, for every project |
If you run your own gateway, the rule belongs wherever you already terminate TLS and normalise headers, not scattered across services — the same argument as sequencing an Envoy Gateway upgrade at the edge rather than per workload.
Every source that recommends the proxy rule also draws the same boundary, and it is the sentence to take to your change review.
Neither stopgap covers Brotli responses that your application fetches from other servers. Only a runtime upgrade removes the flaw.
That is Aikido, which recommends the rule and says it used exactly this on internal services it could not upgrade immediately. Vercel's bulletin is identical in substance: its rules "do not cover responses your functions fetch from other servers", and self-hosted Next.js still needs the runtime upgrade because "Next.js does not block Brotli responses in image optimization".
The reason is structural. The built-in fetch() decompresses Brotli responses automatically, so the dangerous bytes arrive as the reply to a call your own code chose to make. No inbound rule sees them. A hostile or compromised upstream — a partner API, a webhook target you poll, an image you proxy — reaches the decoder without ever sending you a request.
So the rule is worth shipping on anything you cannot patch today, and it is not remediation. If your change log records "mitigated at the edge" and closes the ticket, the ticket is wrong. This is the same triage discipline that self-hosted Next.js exposure keeps demanding: the managed platform's protections and your own deployment's protections are different sets, and the gap between them is where the work is.
Ship the rule, then spend the time it buys on the outbound inventory rather than on more edge rules. List every third-party host your services call, which of those calls use the built-in fetch(), and which run on a Node line still awaiting an upgrade. That list is the real remediation plan, and most teams discover it is shorter than feared and in places they had forgotten.
Two things that are not on the list: distro-packaged Node may link the system Brotli library rather than the bundled copy, in which case the fix arrives through your distribution's package instead, and Bun carried the same flaw until 1.4.4. Neither is helped by an edge rule either.
Date the decision in writing. As of 23 October 2026 there was no reported exploitation in the wild, which is what makes a short mitigation window defensible rather than negligent — and it is exactly the fact that will have changed by the time someone reads your change log and asks why the rule was considered sufficient.
Then upgrade. If you build and operate API integrations against services you do not control, the outbound path is the one that will still be open after the edge rule is in place, and it is the only one a runtime upgrade actually closes.
Use a map block to test $http_content_encoding for br with a case-insensitive word-boundary pattern, then return 415 in the location before proxy_pass. The word-boundary match matters because clients may send a list such as gzip, br that a plain equality test against br would miss.
No. A proxy rule only filters inbound requests. The built-in fetch() decompresses Brotli responses automatically, so a hostile upstream still reaches the decoder through a reply to a call your own code made. Only upgrading to Node.js 22.23.4, 24.22.1 or 26.12.1 removes the flaw.
Vercel added firewall rules on 21 October 2026 that apply automatically to every project at no cost, covering traffic passing through its network. Vercel states the rules do not cover responses your functions fetch from other servers, and that they reduce exposure without replacing patching.
No. Content-Encoding on a request describes the body a client sent you, while Accept-Encoding is how clients ask for compressed responses. Rejecting Brotli request bodies leaves your outbound response compression untouched, so browsers continue receiving Brotli-compressed pages as before.
Ready to take the first step towards unlocking opportunities, realizing goals, and embracing innovation? We're here and eager to connect.