Server

Node2Shell Fix: Update Node.js on cPanel, aaPanel, FastPanel & SSH

Node2Shell (CVE-2026-111497) and 9 more Node.js flaws were patched in October 2026. Update to 24.22.1, 22.23.4 or 26.12.1 on any panel or SSH, zero downtime.

AAdminOctober 23, 202614 min read

On 21 October 2026, the same day PHP shipped its emergency PHP2Shell fixes, the Node.js project released security updates for 10 vulnerabilities across every supported release line. The headline bug, CVE-2026-111497, is an out-of-bounds write in the Brotli decompressor built into Node.js that the project says can allow remote code execution. Security researchers quickly nicknamed it Node2Shell, and by 22 October a proof of concept had been shown running code against an unmodified Node.js 24 build.

If you run an Express API, a Next.js or NestJS backend, a webhook service, a crawler, a Discord or WhatsApp bot, or any app that calls fetch(), you need to read this. Below we explain the bugs in plain language, tell you which Node.js version to use, and walk through updating on cPanel (Application Manager and CloudLinux Node.js Selector), aaPanel, FastPanel and plain SSH with nvm, NodeSource, PM2 and Docker, plus how to use Cloudflare as a temporary shield and how to roll out the update without downtime.

Node2Shell and the October 2026 Release in 60 Seconds

  • Released: 21 October 2026, fixes for 10 CVEs.
  • Patched versions: Node.js 26.12.1, 24.22.1 and 22.23.4.
  • Most serious: CVE-2026-111497 (Node2Shell), High severity, Brotli decoder out-of-bounds write that can lead to remote code execution or a crash.
  • Also High: a DNS hostname truncation bug that can bypass SSRF allowlists, and two TLS hostname verification bypasses.
  • Unsupported versions: Node.js 25, 23, 20, 18 and older are end of life. They are affected and will not get fixes. Upgrade to 22, 24 or 26.
  • Exploitation status: No confirmed attacks in the wild as of 22 October, but public proof-of-concept code exists, so expect that to change.
  • Real fix: Update the Node.js runtime, rebuild container images and restart every Node process. Updating npm packages alone does not fix it.

What Is Node2Shell (CVE-2026-111497)?

Brotli is a compression format, much like gzip, used widely on the web. Node.js ships its own copy of Google's Brotli decoder and exposes it through the built-in zlib module. The bug lets a malformed Brotli stream make the decoder write past the end of its memory buffer. Memory writes in the wrong place can crash the process or, with careful shaping, let an attacker run their own code.

The bug was reported by Matteo Collina and fixed by pulling in an upstream Brotli patch. On 22 October, the first public proof of concept only worked against a deliberately weakened build, but later the same day researchers reported code execution against an unmodified Node.js 24.22.0 image on Linux arm64. It did not work every time, and 24.22.1 rejects the same input.

Is My App Actually Exposed?

Node.js does not decode Brotli on its own. You are exposed when your code or a library decompresses Brotli data an attacker controls. The common paths are:

  • Your app calls fetch(). Node's built-in fetch() (undici) automatically decodes responses that carry Content-Encoding: br, even if you did not ask for Brotli, and there is no option to switch it off. Any URL a user can choose, or a server an attacker controls, can send a booby-trapped response.
  • Express 5 / body-parser 2.x APIs. These decompress request bodies sent with Content-Encoding: br, so any client on the internet can send one. Express 4 (body-parser 1.x) rejects Brotli request bodies with a 415 error.
  • Direct use of zlib.brotliDecompress or zlib.createBrotliDecompress on untrusted data.
  • HTTP clients that decompress by default, such as axios, node-fetch and got.

The highest-risk workloads are link previewers and unfurlers, webhook senders, crawlers, RSS readers, image proxies, AI agent tools that fetch arbitrary pages, and public Express 5 APIs.

The Other 9 Node.js Vulnerabilities Fixed

  • CVE-2026-105482 (High), DNS NUL truncation: hostnames containing a NUL byte were cut short in dns.resolve, so Node could look up a different name than the one you checked. This can defeat SSRF protections and allowlists.
  • CVE-2026-105483 (High), fullwidth-digit TLS bypass: Unicode fullwidth digits were treated differently from normal digits during TLS hostname checks (26.x and 24.x).
  • CVE-2026-106069 (High), loose-IP TLS bypass: certificate hostname validation could accept hosts that only loosely resolve to an IP, enabling impersonation.
  • CVE-2026-105481 (Medium), HTTP keep-alive desync: a race could match a response to the wrong request on a reused connection.
  • CVE-2026-106072 (Medium), non-canonical IPv4 SANs: certificates could authenticate IPv4 addresses written in unusual formats.
  • CVE-2026-106074 (Medium), repeated random values: entropy caches for crypto.randomUUID() and randomInt() could be baked into startup snapshots and Single Executable Applications, so every launch repeated the same "random" values.
  • CVE-2026-106070 (Low), ZipFile disclosure (26.x only).
  • CVE-2026-106071 and CVE-2026-106073 (Low), Permission Model bypasses: wildcard rules and fs.realpathSync could grant wider file access than intended.

The releases also update bundled c-ares, Undici, OpenSSL (on 24.x and 22.x) and SQLite (on 22.x), and remove trust for the eMudhra intermediate certificate authority.

If you built a Single Executable Application on a vulnerable version, rebuild it and regenerate any secrets it created, because of CVE-2026-106074.

Which Node.js Version Should You Use?

  • Node.js 24.22.1 (recommended for most production apps): The mainstream LTS line, widely supported by frameworks and hosting panels.
  • Node.js 22.23.4: Patched and fine to stay on for now, but 22.x is in maintenance and reaches end of life in April 2027. Plan your move to 24.
  • Node.js 26.12.1: The newest line, moving into LTS this month. Good for new projects once your dependencies support it.
  • Node.js 20, 18, 23, 25 and older: End of life and unpatched. Upgrade to 22 or 24. This is a major version change, so test your app first.

Check what you are running:

node -v
which -a node        # every node binary on the PATH
npm ls express body-parser

A version string is not always the whole story. Linux distribution packages (Debian, Alpine, Fedora, RHEL) sometimes link the system Brotli library, so also check your distribution's Brotli advisory. One researcher published a quick check that reads a constant added by the fix:

node -p "require('zlib').constants.BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH || 'missing'"
# -17 means the Brotli fix is present; "missing" means it is not

Before You Update: The No-Downtime Checklist

  1. Back up or snapshot the server, and make sure your app code is committed to Git.
  2. Find every Node.js runtime: system Node, nvm versions, panel-managed versions, CI runners and Docker images.
  3. Test the new version on staging if you are changing major version (for example 20 to 24). Patch updates inside a line (24.x to 24.22.1) rarely break anything.
  4. Use PM2 cluster mode or two instances behind Nginx so one process can restart while the other serves traffic.
  5. Reinstall native modules after a major upgrade (npm rebuild or a clean npm ci). Modules like bcrypt, sharp and sqlite3 are compiled for a specific Node version.
  6. Restart every Node process. A running process keeps the old runtime in memory until it restarts.

How to Update Node.js on cPanel

cPanel servers run Node.js apps in one of two ways.

cPanel Application Manager (ea-nodejs)

WHM installs Node.js as ea-nodejs packages. The patched ea-nodejs22 is 22.23.4.

  • WHM: go to Software > EasyApache 4 or rely on automatic updates (Server Configuration > Update Preferences), then restart the apps in cPanel > Application Manager.
  • SSH as root:
sudo dnf update 'ea-nodejs*'      # "yum" on older systems
/opt/cpanel/ea-nodejs22/bin/node -v

Then restart each application from Application Manager (it runs on Passenger, which starts new processes with the new binary).

CloudLinux Node.js Selector (alt-nodejs)

On CloudLinux servers, apps created with Setup Node.js App use alt-nodejs packages. CloudLinux also patches older lines here. The minimum fixed releases are alt-nodejs22 release 2, alt-nodejs24 release 2, alt-nodejs26 release 1, alt-nodejs20 release 15 and alt-nodejs18 release 26.

rpm -qa 'alt-nodejs*'
sudo yum update 'alt-nodejs*'

# Restart an app (or use the Restart button in "Setup Node.js App")
cloudlinux-selector restart --json --interpreter nodejs --user USERNAME --app-root APP_ROOT

As a cPanel user without root: open Software > Setup Node.js App, edit your application, select the newest patched Node.js version in the dropdown, save, and click Restart. If you change the major version, click Run NPM Install before restarting.

Note that alt-nodejs bundles its own Brotli, so updating the system brotli package does not fix it.

How to Update Node.js on aaPanel

  1. Log in to aaPanel and open App Store. Install or open the Node.js version manager.
  2. Install the patched version (24.22.1, 22.23.4 or 26.12.1). If the manager does not show it yet, use the SSH method below.
  3. Go to Website > Node project, edit your project, select the new Node.js version and save.
  4. Restart the project. If you run with PM2 in cluster mode, reload instead (see the PM2 section) for zero downtime.

Over SSH, aaPanel keeps Node versions under /www/server/nodejs/:

ls /www/server/nodejs/
for n in /www/server/nodejs/*/bin/node; do echo "$n: $($n -v)"; done

How to Update Node.js on FastPanel

FastPanel serves Node.js apps through a reverse proxy, and the Node runtime itself is usually installed on the server with nvm or NodeSource. Update the runtime with one of the SSH methods below, then restart the app's process (PM2 or the systemd service you created). Check the site's proxy settings in FastPanel still point to the right port afterwards.

How to Update Node.js Manually Over SSH

Option 1: nvm (Per-User Installs)

nvm install 24          # installs the latest 24.x, i.e. 24.22.1 or newer
nvm alias default 24
node -v
cd /path/to/app && npm ci   # rebuild native modules for the new runtime

Option 2: NodeSource (System-Wide on Ubuntu/Debian)

curl -fsSL https://deb.nodesource.com/setup_24.x | sudo -E bash -
sudo apt-get install -y nodejs
node -v

On AlmaLinux or Rocky Linux use https://rpm.nodesource.com/setup_24.x and sudo dnf install -y nodejs.

Option 3: Distribution Packages

apt upgrade nodejs or dnf upgrade nodejs works if your distribution has shipped the fix. Distribution builds often lag the official releases, so check the version carefully.

Restart With PM2 Without Downtime

If Node was updated in place (NodeSource or a distro package), the node path stays the same and a rolling reload is enough:

pm2 reload all          # cluster mode: restarts workers one by one, zero downtime
pm2 update              # refreshes the PM2 daemon itself on the new runtime
pm2 save

If you used nvm, the path to node changes. Start the app with the new interpreter and remove the old process once the new one is healthy, or run pm2 update in a quiet moment:

pm2 start ecosystem.config.js --interpreter $(which node)
pm2 save

For apps run by systemd, sudo systemctl restart myapp restarts them. Run two instances behind Nginx (an upstream with two ports) and restart them one at a time to avoid any gap.

Docker and Kubernetes

# Update your Dockerfile base image, e.g. FROM node:24.22.1-alpine
docker build --pull --no-cache -t myapp:latest .
docker compose up -d --force-recreate
docker exec <container> node -v

Images pinned to old tags or digests stay vulnerable until you change them. On Kubernetes, update the image tag in the Deployment for a rolling update.

Temporary Mitigations If You Cannot Update Today

These lower the risk from Node2Shell while you schedule the update. They do not replace it.

Block Brotli Request Bodies at Nginx or Apache

This protects Express 5 style APIs from inbound attacks:

# Nginx, inside the server block that proxies to Node
if ($http_content_encoding ~* "br") {
    return 415;
}
# Apache, with mod_rewrite
RewriteEngine On
RewriteCond %{HTTP:Content-Encoding} br [NC]
RewriteRule ^ - [R=415,L]

Normal browsers do not send Brotli-compressed request bodies, so this rarely affects real users. It does not affect Brotli compression of your responses to visitors.

Turn Off Decompression in Your Code

  • Express 5 body parsers: express.json({ inflate: false })
  • axios: decompress: false
  • node-fetch 3: compress: false
  • got: decompress: false

Built-in fetch() has no off switch, so services that fetch user-supplied URLs should be updated first. Where possible, only fetch from an allowlist of trusted hosts.

Other Quick Wins

  • Validate hostnames for NUL bytes before DNS lookups (CVE-2026-105482).
  • Pin certificates or public keys for sensitive internal TLS connections (the TLS bypasses).
  • Disable keep-alive to sensitive upstreams, or terminate it at a trusted reverse proxy (CVE-2026-105481).
  • Do not treat the experimental --permission flag as a security boundary on vulnerable versions.

Use Cloudflare as a Temporary Shield

Cloudflare can stop malicious Brotli request bodies before they reach your server:

  1. Proxy your API domain through Cloudflare (orange cloud on).
  2. Go to Security > WAF > Custom rules > Create rule.
  3. Use this expression and set the action to Block:
any(http.request.headers["content-encoding"][*] contains "br")
  1. Lock your origin so it only accepts traffic from Cloudflare's IP ranges, otherwise attackers can hit the server's IP directly:
for ip in $(curl -s https://www.cloudflare.com/ips-v4); do sudo ufw allow from $ip to any port 80,443 proto tcp; done
for ip in $(curl -s https://www.cloudflare.com/ips-v6); do sudo ufw allow from $ip to any port 80,443 proto tcp; done

Remember that no WAF can protect responses your app fetches from other servers. If your app calls fetch() on URLs users provide, only the runtime update closes that hole. Vercel also added inbound firewall rules for its customers on 21 October.

After Updating: Test and Harden

  • Confirm node -v shows 26.12.1, 24.22.1 or 22.23.4 (or newer) for every runtime and container.
  • Test HTTPS connections to your APIs and databases, DNS lookups, file uploads and anything that handles compressed data.
  • Run npm audit and update dependencies while you are at it.
  • Remove Node.js versions nobody uses, and turn on automatic security updates for the OS.
  • Watch the official Node.js security blog and subscribe to your panel vendor's announcements.

Conclusion

The October 2026 Node.js security release fixes ten bugs, and Node2Shell (CVE-2026-111497) is the one to move on fast, because built-in fetch() and Express 5 make the Brotli decoder reachable in many ordinary apps. Update to Node.js 24.22.1, 22.23.4 or 26.12.1, rebuild your containers, and roll out with a PM2 cluster reload or one-at-a-time restarts so users never notice. Use Nginx rules and a Cloudflare WAF rule as a short bridge, and move off Node.js 20 and older for good.

Need a hand updating Node.js across cPanel, aaPanel, FastPanel or your own VPS? The Papaya Coders team can audit your runtimes, patch them safely and set up zero-downtime deployments for the future.

Frequently Asked Questions

What is Node2Shell?

Node2Shell is the nickname for CVE-2026-111497, a high-severity out-of-bounds write in the Brotli decoder bundled with Node.js. It was patched on 21 October 2026 and can lead to remote code execution or crashes when an app decompresses attacker-controlled Brotli data.

Which Node.js versions are patched?

Node.js 26.12.1, 24.22.1 and 22.23.4 contain the fixes. Node.js 20, 18, 23, 25 and older are end of life and will not be patched.

Is my Express app vulnerable to Node2Shell?

Express 5 with body-parser 2.x decompresses Brotli request bodies, so it is exposed until you update Node.js or block Content-Encoding: br requests. Express 4 rejects Brotli request bodies, but your app can still be exposed through fetch() or other HTTP clients.

Does npm update fix Node2Shell?

No. The bug is in the Node.js runtime, so you must install a patched Node.js version and restart your app. Updating npm packages alone is not enough.

How do I update Node.js on cPanel?

Use Setup Node.js App to switch your app to the newest patched version and restart it, or ask your host to update the ea-nodejs or alt-nodejs packages. Root users can run dnf update 'ea-nodejs*' or yum update 'alt-nodejs*'.

Can I update Node.js without downtime?

Yes. Run your app in PM2 cluster mode and use pm2 reload all, or run two instances behind Nginx and restart them one at a time.

Does Cloudflare protect against Node2Shell?

A Cloudflare WAF custom rule can block Brotli-encoded request bodies before they reach your server, but it cannot protect data your app fetches from other servers. Treat it as temporary and update Node.js.

Which Node.js version should I use in 2026?

Node.js 24 LTS is the best choice for most production apps. Node.js 22 is still supported until April 2027, and Node.js 26 is the newest line for new projects.

Need help with your project?

Talk to the Papaya Coders team for a free consultation.

Contact Us