Direct answer: CVE-2026-111497, also called Node2Shell or Brotli2Shell, is an out-of-bounds write flaw in the Brotli decoder 1.0.3 to 1.2.0. An app that opens Brotli data from outside can crash, leak memory, or run attacker code. CISA KEV added the flaw to its list of exploited flaws on 27 October 2026. Update Node.js today to 22.23.4, 24.22.1, or 26.12.1.

Node.js is not the only affected product. The same decoder is in Bun, the Python packages brotli and brotlicffi, .NET 8 to 11, Envoy, Istio, and the libbrotli1 package on Debian and Ubuntu.

Main condition: Node.js from nodejs.org, nvm, and the official Docker image carries its own decoder, so you update Node.js. Node.js from Ubuntu and Debian apt uses the system library, so you update libbrotli1. Limit: The temporary steps in this article only reduce exposure. This article contains no exploit code.

We read the Node.js advisory of 21 October, the Brotli 1.2.1 release, the .NET advisory of 25 October, the PyPI advisory, the Ubuntu CVE page, the Debian tracker, and CISA KEV on 30 October 2026, at about 13:30 UTC. We ran the commands in steps 1 to 5 in podman containers with the official Node.js 24.22.0 and 24.22.1, Ubuntu 24.04, Python 3.13, .NET runtime 8.0.32 and 8.0.33, and nginx 1.29 images on the same date. The test server holds no customer data.

The problem: a Node.js update alone does not close every path

The flaw is in a library, not in one app. A server with an updated Node.js can stay vulnerable through Python, .NET, or the system library.

According to Tenable, Google put the fix in the Brotli source code on 27 February 2026. Node.js and Google released versions with the fix only on 21 October 2026. One day later, researchers ran code on the official Node.js 24.22.0 image. On 26 October, ELLIO recorded an exploitation attempt on Node.js 24.22.0 on x86-64.

There are 2 more traps. First, process.versions.brotli prints 1.2.0 on a vulnerable Node.js and on a patched Node.js. Our test in step 1 shows the same result as the ELLIO note. Second, a process that ran before the update keeps the old decoder until it restarts.

Check Point wrote on 29 October that a security team must not close the incident after a Node.js patch alone. The inventory must include runtimes, language packages, proxies, service meshes, containers, and software that carries its own Brotli library.

Timeline from 27 February to 10 November 2026: the Google fix, Node.js releases, CVE publication, distro and .NET patches, the ELLIO attempt, CISA KEV, CSA, and the CISA deadline.
Grey dots: patch releases. Red dots: proof of code execution, the attack attempt, and security agency decisions. The first reported attack attempt came 5 days after the Node.js patch. Source: Tenable, Node.js, Ubuntu, Debian, Microsoft, ELLIO, CISA KEV, and CSA.

This month we also covered the PHP2Shell flaws and the GitLab CVSS 10 flaws. The same pattern came back: the gap from patch to attack attempt was only a few days. For this flaw, the gap was 5 days.

How it works: broken Brotli data makes the decoder write past a buffer

The decoder reads broken data as data that is not complete yet. As a result, the decoder keeps writing into a small buffer until it goes past its end.

This section uses the summary from the official advisories. Its purpose is to help you pick the right step, not to explain an attack.

Summary from the Node.js advisory

According to the Node.js advisory of 21 October, an invalid block switch was reported as a need for more input, not as a format error. The streaming decoder kept adding input bytes to an 8-byte internal buffer, then wrote past the end of that buffer (CWE-787). CISA names the flaw "Google Brotli Unchecked Return Value Vulnerability".

Node.js rates it High and writes that the flaw can allow remote code execution. The 22, 24, and 26 branches are affected. The 20, 23, and 25 branches are affected too, but their support has ended and they get no fix.

Scores from each body

Scores differ per source, so write each score with its source. NVD gives CVSS 3.1 9.8. Google as the CNA gives CVSS 4.0 9.2. Microsoft gives 8.1 for .NET, because Brotli decompression in .NET is off by default.

Red card for the exploited CVE-2026-111497, a list of 6 products that carry the Brotli decoder, the NVD 9.8 score, and a teal box: update, then restart.
(1) Red card: the decoder flaw and its effect. (2) Amber card: products that carry the same decoder. (3) Score row: each body gives its own score. (4) Teal box: only an update and a restart close the flaw. Source: Node.js, Google Brotli, Microsoft, NVD, and CISA KEV.

Exploitation status as of 30 October

CISA KEV added the flaw on 27 October 2026 based on evidence of active exploitation. ELLIO recorded 1 Brotli request of about 23 MB to Node.js 24.22.0 on 26 October, at 15:08 UTC. In 50 attempts in the ELLIO lab, that attacker chain did not produce a shell.

Check Point reports that 90.5% of the events in its telemetry carried Brotli-encoded HTTP payloads, and 24.5% targeted upload endpoints. Tenable has not independently confirmed the activity that ELLIO reported. The Singapore CSA asked for an immediate patch on 30 October 2026.

Who is most at risk

Apps that open Brotli-encoded request bodies or responses from outside parties are most at risk. MCPMCPA standard that lets an AI program use your tools and data under clear permissions.Open the glossary servers, chatbots, and APIAPIThe official door 2 systems use to exchange data, without anybody copying it by hand.Open the glossary backends on Node.js often use Express and fetch(), so they are in this group.

This table sums up Aikido, ELLIO, the .NET advisory of 25 October, and Tenable.

How the app uses BrotliRiskWhat you update
Express 5 or body-parser 2 accepts Content-Encoding: br bodiesHighNode.js
Koa 3 with @koa/bodyparser 6High, tested by ELLIONode.js
fetch() to user URLs, webhooks, scrapers, or AI agentsHigh, a proxy cannot stop itNode.js
zlib.brotliDecompress on uploaded filesHighNode.js
Python requests, urllib3, or httpx with the brotli package installedHigh for outside URLspip brotli or brotlicffi
ASP.NET Core or HttpClient with br decompression onWhen turned on.NET runtime, republish NativeAOT
Envoy or Istio with the Brotli decompressor filterWhen turned onEnvoy or Istio
Node.js from Ubuntu or Debian aptFollows the system librarylibbrotli1, then restart
Six risk cards: Express 5, fetch to outside URLs, and zlib Brotli on uploads are high risk, Python and .NET when Brotli is on, plain node:http is low, then a check command.
Red cards: the app opens outside Brotli data on its own. Amber cards: the risk appears when a Brotli package or setting is on. Bottom box: 2 commands that find packages and code that open Brotli. Source: Node.js, Aikido, ELLIO, Microsoft, and Tenable.

A plain node:http server does not open Brotli bodies itself, according to Aikido. Update anyway, because a package in node_modules can open them without your knowledge.

Versions that carry the fix

Update each product to the minimum version in this table or to a newer version in the same branch.

ProductMinimum safe versionNote
Node.js 2222.23.4Official binary, nvm, Docker image
Node.js 2424.22.1Official binary, nvm, Docker image
Node.js 2626.12.1Official binary, nvm, Docker image
Node.js 20, 23, 25No fixMove to 22, 24, or 26
Bun1.4.4Rebuild compiled executables
Google Brotli1.0.10, 1.1.1, 1.2.1Apps that bundle the library
pip brotli / brotlicffi1.2.1 / 1.2.1.0Every virtualenv and image
.NET 8 / 9 / 108.0.33 / 9.0.22 / 10.0.14Republish self-contained and NativeAOT apps
Envoy1.36.12, 1.37.8, 1.38.6, 1.39.3When the Brotli decompressor is on
Istio1.29.9, 1.30.6, 1.31.2When Brotli decompression is on
Table of minimum safe versions for Node.js, Bun, the Brotli library, pip, and .NET, a box of Ubuntu and Debian libbrotli1 versions, and a note on process.versions.brotli.
Teal column: the target versions. Red row: Node.js branches with no fix. Top right: distro packages. Bottom right: why the Brotli version inside Node.js is not proof of safety. Source: Node.js, Google Brotli, PyPI, Microsoft, Ubuntu, and Debian.

For distro packages, use the versions from the Ubuntu CVE page and the Debian tracker. According to both sources, the apt nodejs package on Ubuntu 22.04 and newer and on Debian uses the system library, so a libbrotli1 update closes the flaw in that Node.js.

Releaselibbrotli1 with the fix
Ubuntu 22.04 LTS1.0.9-2ubuntu0.1
Ubuntu 24.04 LTS1.1.0-2ubuntu0.1
Ubuntu 26.04 LTS1.2.0-3ubuntu0.1
Debian 12 (bookworm)1.0.9-2+deb12u1
Debian 13 (trixie)1.1.0-2+deb13u1

PHP has a path too. According to Tenable, the official PHP builds for Windows are affected through the cURL extension when automatic decompression is on, with fixes in 8.2.35-1, 8.3.36-1, 8.4.27-1, and 8.5.12-1. PHP on Linux follows the system library or the PHP brotli extension, which has the fix in 0.21.1.

Prerequisites

  • SSH access with sudo rights to the server, or docker exec access to the container.
  • A list of every place where Node.js, Python, and .NET run: servers, CI runners, container images, and serverless functions.
  • Access to the app repo to change the Dockerfile, package.json, and requirements.txt.
  • A short restart window for each service.
  • Read access to the nginx or load balancer logs, the systemd journal, and PM2.

When your Node.js servers hold tool access for AI agents, also read about access rights and audit logs for an MCP server. That guide explains how to limit what a compromised process can reach.

Step 1: Check the Node.js version on every server, CI runner, and container

Save this script as check-node.sh. The script reads the Node.js version and how it was built, then compares the version with the fix for its branch.

command -v node >/dev/null || { echo "Node.js is not installed on this machine."; exit; }
v=$(node -p process.versions.node)
if [ "$(node -p process.config.variables.node_shared_brotli)" = "true" ]; then
  echo "$v: uses the system Brotli. Check libbrotli1 in step 2."; exit; fi
case ${v%%.*} in
  22) fix=22.23.4;; 24) fix=24.22.1;; 26) fix=26.12.1;;
  *) echo "$v: branch without a fix. Move to Node.js 22, 24, or 26."; exit;;
esac
lt() { [ "$1" != "$2" ] && [ "$(printf '%s\n' "$1" "$2" | sort -V | head -1)" = "$1" ]; }
if lt "$v" "$fix"; then echo "$v: VULNERABLE to CVE-2026-111497. Update to $fix."
else echo "$v: has the Brotli fix (minimum $fix)."; fi

Run the script on the server, in running containers, and on images before deploy.

bash check-node.sh                                        # server or CI runner
docker exec -i container-name bash < check-node.sh        # running container
docker run --rm -i --entrypoint bash node:24.22.0 < check-node.sh   # image before deploy
Terminal: the check on Node.js 24.22.0 prints VULNERABLE, on 24.22.1 has the fix, process.versions.brotli prints 1.2.0 on both, and Ubuntu apt Node.js uses the system Brotli.
Lines 3 and 4 hold the main lesson: the Brotli version inside Node.js is the same, although one is vulnerable and one is safe. The test used the official node 24.22.0 and 24.22.1 images and ubuntu 24.04. Source: Rama Digital test in podman, 30 October 2026.

Alpine-based images do not include bash. For those images, run node -v, then compare the result with the version table. For Bun, run bun --version. Versions below 1.4.4 are vulnerable.

Check the result: The output says "has the Brotli fix". A "VULNERABLE" result means Node.js must update today. A "uses the system Brotli" result means you go to step 2 for libbrotli1.

Step 2: Check libbrotli1, Python packages, and .NET

Save this script as check-lib.sh. The script checks the system library on Debian and Ubuntu, the pip packages brotli and brotlicffi, and the .NET runtimes.

lt() { [ "$1" != "$2" ] && [ "$(printf '%s\n' "$1" "$2" | sort -V | head -1)" = "$1" ]; }
# 1. System Brotli library on Debian and Ubuntu
. /etc/os-release
case $VERSION_CODENAME in
  jammy) fix=1.0.9-2ubuntu0.1;; noble) fix=1.1.0-2ubuntu0.1;; resolute) fix=1.2.0-3ubuntu0.1;;
  bookworm) fix=1.0.9-2+deb12u1;; trixie) fix=1.1.0-2+deb13u1;; *) fix=;;
esac
cur=$(dpkg-query -W -f='${Version}' libbrotli1 2>/dev/null)
if [ -z "$cur" ]; then :
elif [ -z "$fix" ]; then echo "libbrotli1 $cur: check your distro advisory."
elif dpkg --compare-versions "$cur" lt "$fix"; then echo "libbrotli1 $cur: VULNERABLE. Update to $fix."
else echo "libbrotli1 $cur: has the fix."; fi
# 2. Python packages brotli and brotlicffi
for py in python3 python; do command -v $py >/dev/null && break; done
for pkg in brotli:1.2.1 brotlicffi:1.2.1.0; do
  v=$($py -c "import importlib.metadata as m; print(m.version('${pkg%%:*}'))" 2>/dev/null) || continue
  if lt "$v" "${pkg#*:}"; then echo "pip ${pkg%%:*} $v: VULNERABLE. Update to ${pkg#*:}."
  else echo "pip ${pkg%%:*} $v: has the fix."; fi
done
# 3. .NET runtimes
dotnet --list-runtimes 2>/dev/null | while read -r name v rest; do
  case $v in 8.*) fix=8.0.33;; 9.*) fix=9.0.22;; 10.*) fix=10.0.14;; *) continue;; esac
  if lt "$v" "$fix"; then echo "$name $v: VULNERABLE. Update to $fix."
  else echo "$name $v: has the fix."; fi
done
bash check-lib.sh                                  # server
source .venv/bin/activate && bash check-lib.sh     # Python virtualenv
docker exec -i container-name bash < check-lib.sh  # container
Terminal: the library check prints VULNERABLE for libbrotli1 1.1.0-2build2, pip brotli 1.2.0, and .NET 8.0.32, then has the fix for 1.1.0-2ubuntu0.1, 1.2.1, and 8.0.33.
Each pair of lines compares an old and a new version from the same official image. The test used ubuntu 24.04, python 3.13-slim, and dotnet/runtime 8.0.32 and 8.0.33. Source: Rama Digital test in podman, 30 October 2026.

The script prints a line only for the components on that machine. For the RHEL family, run rpm -q brotli and compare it with your distro advisory. For Envoy and Istio, run envoy --version or istioctl version, then compare it with the version table.

Self-contained and NativeAOT .NET apps carry the decoder inside the app file. According to the .NET advisory of 25 October, a runtime update on the machine does not fix those apps. Republish the app with the patched packages.

Check the result: Each line says "has the fix". Run the script in each Python virtualenv, because each virtualenv has its own pip packages.

Step 3: Update, then restart every process

Update the vulnerable components, then restart every process that uses them. Use the command that matches how you installed each component.

# Node.js through nvm
nvm install 24.22.1 && nvm alias default 24.22.1
# Dockerfile: FROM node:24.22.1-bookworm-slim, then rebuild with the new base image
docker build --pull -t app:patch .
docker compose up -d --force-recreate
# System library on Debian and Ubuntu
sudo apt update && sudo apt install --only-upgrade libbrotli1
# Python packages
pip install -U 'brotli>=1.2.1' 'brotlicffi>=1.2.1.0'
# Bun
bun upgrade

Use an image tag with the full version, or rebuild with --pull so that the base image is new too. Aikido notes that an image with an old tag, for example node:24.22.0, stays vulnerable until you rebuild it. For .NET, install runtime 8.0.33, 9.0.22, or 10.0.14, then republish self-contained apps.

After a system library update, save this script as check-restart.sh. The script finds processes that still use the old Brotli library from memory.

n=0
for m in $(grep -l "libbrotli.*(deleted)" /proc/[0-9]*/maps 2>/dev/null); do
  p=${m#/proc/}; p=${p%/maps}; n=$((n + 1))
  echo "PID $p still uses the old Brotli: $(tr "\0" " " < /proc/$p/cmdline)"
done
echo "Processes to restart: $n"
sudo bash check-restart.sh
sudo systemctl restart service-name   # systemd service
pm2 reload all                        # PM2 apps
Terminal: apt replaces libbrotli1 with 1.1.0-2ubuntu0.1, the script finds 1 node process that still uses the old library, then after a restart the script prints 0.
A process that ran before the update keeps the old decoder in memory. A package update alone does not close the flaw until that process restarts. Source: Rama Digital test in podman, 30 October 2026.
A 6-step ladder: update Node.js and Bun, update other libraries, and restart processes, then 3 steps with a not-a-fix label: reject br bodies, turn off decompression, check signs.
(1) to (3) Teal boxes: fixes that close the flaw. (4) to (6): temporary steps. The red labels remind you that those steps do not make the server safe. Source: Node.js, Microsoft, Tenable, and Check Point.

The script sees only the system library. Official Node.js carries the decoder inside the node binary, so restart every Node.js service after the update. Serverless functions and hosting platforms need a new deploy so that the build uses the new runtime.

Check the result: Repeat steps 1 and 2. Every line says "has the fix", and check-restart.sh says "Processes to restart: 0".

Step 4 (optional): Reject Brotli bodies for a short time when you cannot update yet

Use this step only for a short gap until the update is done. The Node.js advisory of 21 October gives no workaround, and Tenable writes that a proxy block does not protect responses that the app fetches from outside servers.

In nginx, reject requests with the Content-Encoding: br header. Put the if line in the server block that accepts API calls and uploads, then run sudo nginx -t and sudo systemctl reload nginx.

server {
    listen 80;
    # Reject Brotli bodies until every app behind the proxy is patched.
    if ($http_content_encoding ~* "\bbr\b") { return 415; }
    location / { return 200 "ok\n"; }
}

In Express, reject Brotli bodies before express.json() and other parsers open them.

// Reject Brotli bodies before the body parser opens them.
app.use((req, res, next) => {
  if (/\bbr\b/i.test(req.headers['content-encoding'] || '')) return res.status(415).send('Brotli not accepted');
  next();
});
app.use(express.json());
Terminal: nginx -t passes, then nginx and the Express 5.3.0 middleware answer HTTP 415 for Content-Encoding br and gzip, br, and HTTP 200 for identity.
The test body is not Brotli data. The rule rejects the request from the header alone, before the app opens the body. The test used the nginx 1.29 image and node 24.22.1 with Express 5.3.0. Source: Rama Digital test in podman, 30 October 2026.

In .NET, the .NET advisory of 25 October asks you to remove the "br" entry from DecompressionProviders and to limit AutomaticDecompression. Microsoft also asks you not to add new decompression settings where none exist.

// ASP.NET Core: remove "br" from the existing DecompressionProviders.
// HttpClient: open only GZip and Deflate.
var handler = new HttpClientHandler {
    AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
};

In Python, Tenable advises you to remove the brotli and brotlicffi packages until the new version is installed. Without those packages, urllib3 and requests do not open Brotli responses. In Envoy and Istio, turn off the Brotli decompressor filter in both directions. Removing br from the Accept-Encoding header alone does not close the path.

Check the result: A request with Content-Encoding: br gets HTTP 415. A request without Brotli still gets HTTP 200.

Step 5: Look for signs that the server was touched

A failed attack often crashes the process. A successful attack can leave no trace in the logs. Save this script as check-signs.sh and run it with sudo on the nginx server.

log() { zcat -f /var/log/nginx/access.log*; }
echo "ELLIO IoC    : $(log | grep -cE "node2shell-check|94\.154\.43\.7")"
echo "Rejected 415 : $(log | awk "\$9 == 415" | wc -l)"
echo "5xx errors   : $(log | awk "\$9 >= 500" | wc -l)"

Then check crashes, restarts, and child processes for the period since 21 October 2026.

sudo journalctl --since 2026-10-21 | grep -ciE 'node.*(segfault|sigsegv|sigabrt)|core dumped'
coredumpctl list node --since 2026-10-21
pm2 list                                        # the ↺ column is the restart count
docker inspect -f '{{.Name}} restart={{.RestartCount}}' $(docker ps -q)
ps -eo pid,ppid,user,etime,cmd --forest | grep -A3 '[n]ode'
Terminal: the sign check on the nginx log prints 0 ELLIO IoC, 10 requests rejected with 415, and 0 5xx errors, then podman inspect prints restart=0 for proxy and api.
The number 10 is our own test requests from step 4. On your server, the 415 count shows how many Brotli bodies the temporary rule stopped. Source: Rama Digital test in podman, 30 October 2026.
Two columns of attack signs: in processes and servers, and in web and proxy logs, then a red box with the action to take when you see a sign: isolate, replace secrets, rebuild.
Amber column: crashes, restart loops, and odd child processes. Red column: large or broken Brotli bodies, IoC from ELLIO, and the error text from a patched version. Source: ELLIO, Check Point, and Tenable.

Look for 4 patterns from ELLIO and Check Point. First, node processes that crash, restart loops, or new core dumps. Second, child processes such as sh, bash, or curl under a node process.

Third, large or broken Brotli bodies, mainly to upload and API endpoints. Fourth, IoC from ELLIO: the user agentAI agentAn AI program that performs work steps by itself, for example reading a message, drafting a reply, and recording the result.Open the glossary node2shell-check, the address 94.154.43.7, and the error ERR__ERROR_FORMAT_BLOCK_SWITCH on a patched version. That error shows that someone is testing your server.

Check the result: The IoC count is 0, there are no crashes or restart loops, and there are no child processes that you do not know. When you see a sign, isolate the server and keep the logs. Limit access to core dumps, because ELLIO writes that they can hold session data. Replace every secret the node process can read: .env values, API keys, database tokens, and cloud tokens.

Example: 1 evening of response for 4 services

This simulation uses dummy data. The service names, times, and results are not customer data.

Time (UTC)Dummy serviceCheckResultAction
12:00shop-api (Docker node:24.22.0, Express 5)Step 1VULNERABLEStep 4 in nginx, then rebuild on 24.22.1
12:40wa-bot (nvm Node.js 22.23.3, webhookWebhookAn automatic message one system sends to another the moment something happens, for example an incoming WhatsApp message.Open the glossary fetch)Step 1VULNERABLEnvm install 22.23.4, pm2 reload all
13:10price-scraper (Python 3.12, brotli 1.1.0)Step 2pip brotli VULNERABLEpip install -U brotli, restart the worker
13:30old-web (Ubuntu 24.04, Node.js from apt)Steps 1 and 2libbrotli1 VULNERABLEapt upgrade, check-restart.sh, restart 2 services
14:00shop-apiStep 53 restarts in a row on 26 OctoberIsolate, keep logs, replace secrets

The lesson from the simulation: the nginx rule does not protect a service that fetches outside URLs. Restart loops before the patch need an investigation, not only an update.

Who installs the patch

The patch duty depends on the hosting type. This table helps you see who must act today.

Hosting typePatch ownerWhat you do
Own VPS or serverYour IT teamSteps 1 to 5
Container or KubernetesThe team that owns the imagesChange the base image, rebuild, then steps 1 and 5
Serverless or hosting platformThe platform and your teamRead the platform notice, then deploy again
App run by a vendorThe vendorAsk for written proof of the version, then the step 5 results

Rama Digital recommendation: when your Node.js server holds payment tokens, WhatsApp tokens, or AI model API keys, treat every sign in step 5 as an incident. For an MCP server, also read about access rights, approval, and audit logs for an MCP server.

Checklist for today

  1. List every place where Node.js, Bun, Python, and .NET run. Owner: DevOps team. Evidence: a list of hosts, images, and CI runners.
  2. Check Node.js with step 1. Owner: server admin. Evidence: script output per host and per image.
  3. Check libbrotli1, pip, and .NET with step 2. Owner: server admin. Evidence: script output per host and per virtualenv.
  4. Update and rebuild images. Owner: developer. Evidence: the new Dockerfile and lockfile.
  5. Restart every process. Owner: server admin. Evidence: check-restart.sh output says 0.
  6. Apply step 4 on services that cannot update yet. Owner: nginx admin. Evidence: the HTTP 415 test.
  7. Look for signs with step 5. Owner: server admin. Evidence: command output, kept with the logs.
  8. Stop when every component says "has the fix" and step 5 is clean. When you see a sign, stop the patch work and start incident response.

Frequently asked questions

I do not use Express. Do I still need to update? Yes. fetch() opens Brotli responses on its own, and other packages in node_modules can open Brotli bodies. A Node.js update is the only complete fix.

process.versions.brotli prints 1.2.0. Is my Node.js safe? Not always. The vulnerable Node.js 24.22.0 and the patched 24.22.1 both print 1.2.0. Check the Node.js version with step 1.

My Node.js comes from Ubuntu apt. What must I update? Update the libbrotli1 package, then restart the Node.js services. Ubuntu writes that the nodejs package on 22.04 and newer uses the system library.

Does a Content-Encoding br block in nginx close the flaw? No. The block stops request bodies from outside. Responses that the app fetches from outside servers are still opened by the decoder.

I still use Node.js 20. When does the fix come? There is no fix. Node.js 20, 23, and 25 are past their support. Move to Node.js 22, 24, or 26.

Is my PHP or WordPress site affected? It can be, through the system library or the PHP brotli extension. Update libbrotli1 and the brotli extension to 0.21.1, then restart PHP-FPM.

How do I know whether the server was broken into? Look for crashes, restart loops, odd child processes, and the IoC in step 5. Clean logs do not prove that the server is safe.

Next step

The limit that still applies: an update closes this flaw, but it does not remove access that an attacker may have planted before the patch. When your services show a sign in step 5, or you need help to check images and secrets after an incident, use Vibe Code Rescue for an audit and stabilisation. For 1 urgent issue today, Book a 30-minute session.

Sources