On 21 October 2026 the Node.js project shipped a security release that fixed ten vulnerabilities across Node 22, 24 and 26. The most serious one, CVE-2026-111497, is in the Brotli decoder that ships inside Node. If an app decompresses Brotli data that an attacker controls, the bug can corrupt memory and, in the worst case, let the attacker run code on the server.
This post covers what the bug is, which Node versions are safe, and exactly what we changed on Riven. Short version: we finished on 23 October, two days after the advisory, and most Riven users don't have to do anything.
What the bug is
Brotli is a compression format, like gzip. Node includes its own copy of the Brotli library so that zlib can compress and decompress it.
CVE-2026-111497 is an out-of-bounds write in that bundled decoder. In simple words: crafted Brotli data can make Node write outside the memory it was supposed to use. That can crash the process, leak data, or in the worst case lead to remote code execution.
The part that makes it easy to miss: your own code doesn't have to call Brotli directly. A library that decompresses request bodies or downloaded files is enough.
Node rated it High. Some national CERTs scored it 9.8 out of 10. As of 22 October there were no public reports of it being used in attacks, but that usually changes once people study the patch.
Which versions are safe
| Release line | Patched in | Status |
|---|---|---|
| Node 26 | 26.12.1 | Supported |
| Node 24 | 24.22.1 | Supported (LTS) |
| Node 22 | 22.23.4 | Supported (LTS) |
| Node 20 and older | No fix | End of life |
If you run Node anywhere, check with node -v. Anything older than the versions above should be upgraded. Node 20 is end of life, so it won't get this fix or any future one.
What we changed on Riven
Everything below was done by 23 October.
Our own platform. Riven's own services moved to Node 26.12.1. We checked the running version of each service after the update, not just the config.
Build templates. Every template that Riven generates for you (Next.js, Nuxt, Vite, Express, Koa and plain Node apps) now uses Node 24.22.1 instead of Node 20. Node 20 is end of life, so it had to go regardless of this bug.
Fresh base images on every build. Each build now pulls a fresh base image. A cached old image can't sneak back in, so the next time a patch like this lands, a redeploy picks it up.
A nodeVersion setting in riven.json. If an older package doesn't work on Node 24 yet, you can pick 22:
{
"nodeVersion": "22"
}
The allowed values are 22 and 24. If you ask for an end-of-life version like 20, the build stops with a clear error instead of quietly building on an unpatched runtime. Your deploy log now shows which Node version the build actually used.
CI and tools. Our CI now runs on the same Node version as production, so what we test is what we ship. The Riven CLI and MCP client now need Node 22 or newer.
An audit of every running service. Changing templates only helps new builds. Apps that were already running still had their old runtime. So we went through every running service and checked the Node version inside the container, not what the config said it should be. Services on an old version were rebuilt on a patched one, and we emailed their owners so nobody had to find out from a changelog.
Do you need to do anything?
If Riven builds your app (you didn't add your own Dockerfile): no. Your service is already on patched Node. If something broke on Node 24, set "nodeVersion": "22" in riven.json and redeploy.
If you deploy with your own Dockerfile: your Node version comes from the FROM line, so you control it. We checked these services too, but if your Dockerfile pins an old tag like node:20 or an exact older version, a rebuild will build the same old Node again. Change it to a patched version, for example FROM node:24-alpine, and redeploy.
If you run Node somewhere else: upgrade to 22.23.4, 24.22.1 or 26.12.1 or newer, and rebuild your images. Bumping a version in a config file doesn't change a container that's already running.
A rough week for platforms
This wasn't the only security news that week. The day before, PHP shipped emergency patches for PHP2Shell. And on 21 October Railway disclosed that an unauthorized party may have accessed encrypted environment variables, some in decrypted form, and paused deployments while it investigated.
These are different kinds of problems and I'm not comparing them. Railway was open about what happened, which is the right thing to do. But it was a good reminder of what users actually want from a platform on a week like this: fix things fast, and tell people what you did without making them dig for it. That's what this post is.
What we're doing next
Doing this by hand once is fine. Doing it for every advisory isn't. We're working on showing the runtime version of each service in the dashboard and flagging services that are on an affected version, so you can see your exposure without waiting for an email.
If you have questions about this patch or about your own service, write to us through the contact page or ask on Discord. You can also read how we protect apps and data on our Security page.
