Node2Shell: Protect Self-Hosted Apps from CVE-2026-111497

A high-severity Node.js vulnerability, tracked as CVE-2026-111497 and known as Node2Shell, sits in how the runtime decompresses Brotli data. It is a flaw in the Node.js (and Bun) runtime itself, not in a framework or dependency, so any app that inflates attacker-controlled Brotli input is at risk.

Node.js shipped patched releases on October 21. By October 22, researchers had published proofs of concept and demonstrated code execution against an unmodified Node.js 24.22.0 build. No exploitation in the wild had been reported as of that date, but the bug handles untrusted network input, public PoCs exist, and the fix is a routine version bump.

What Node2Shell does

The bug is an out-of-bounds write in the bundled Brotli decoder. Malformed compressed input can crash the process, leak part of its memory, or, in the worst possible case, run code with the privileges of the Node process.

Exposure depends on where Brotli data enters. A bare Node HTTP server does not decode incoming Brotli bodies on its own, but here are some common places where it does:

  • Express 5 and body-parser 2.x decompress request bodies sent with Content-Encoding: br
  • Built-in fetch() automatically decompresses Brotli responses, including from servers you do not control
  • Direct use of node:zlib Brotli APIs on untrusted input

Because this is a flaw at runtime, updating Express or your app packages is not going to be enough to protect your apps. You need a patched version of the Node.js (or Bun) binary.

Patch first

Update to a fixed release as soon as you can:

  • Node.js 26.12.1
  • Node.js 24.22.1
  • Node.js 22.23.4
  • Bun 1.4.4 or newer

Check node --version on hosts, CI runners, and inside containers. Rebuild images pinned to older tags; an image left on node:24.22.0 stays vulnerable no matter how often you redeploy it. Node.js 25.x, 23.x, 20.x and earlier are end of life and will not get this fix, so plan a move to a supported line.

If you cannot upgrade immediately, reject inbound Content-Encoding: br at your reverse proxy or load balancer. That reduces request-body exposure, but it does not protect apps that decompress Brotli responses from other servers.

Keep private apps off the open internet

Patching the vulnerability is the best possible solution. Upgrading your access architecture reduces the risk of future vulnerabilities. It can protect you before you even know about the vulnerability and have a chance to patch it.

A lot of self-hosted Node is not meant for anonymous public traffic: admin UIs, internal APIs, staging sites, billing panels, ops dashboards, and webhook receivers. If those apps accept HTTP from the open internet, every new unauthenticated runtime bug is a direct hit on the process.

There are two strong patterns here. Pangolin supports both.

Authenticated reverse proxy

An identity-aware reverse proxy sits in front of the app and requires login before traffic is forwarded. Unauthenticated scanners and exploit traffic stop at the proxy. Even if the underlying Node app is later compromised, you still have a separate access layer controlling who can reach it.

This fits when users need browser access without installing a client, and you are willing to publish a hostname that still requires identity before the origin sees the request.

Identity-based VPN and private reverse proxy

A step further is to take the app entirely off the public internet.

Users connect with an identity-based VPN client over a secure tunnel. Once connected, a reverse proxy serves the app on that private path with a valid certificate, so the browser experience stays as normal HTTPS, but the hostname is only reachable inside the tunnel. From the internet’s point of view, there is nothing to probe. No public listener means no unauthenticated Node2Shell traffic against that app.

This is useful when:

  • the app should only be used by your team or approved machines
  • you want zero public exposure, not just an auth gate on a public URL
  • you still want clean hostnames and TLS for private web apps after the client is connected

Public sites that must stay anonymous still need the Node.js patch immediately. For everything that does not need to be public, stop letting the internet talk to Node directly, either with auth at the edge or by keeping the whole path private.

Conclusion

Node2Shell is a reminder that self-hosted security is layered. First, you should patch the runtime. Then, you can decide which apps truly need a public front door and which should stay private.

About Pangolin

Pangolin is an open-source Secure Access Service Edge (SASE) platform built on WireGuard® that unifies modern networking and security for teams connecting to apps, infrastructure, and AI workloads. Designed as an open, self-hostable alternative to complex legacy suites, Pangolin brings together a zero-trust VPN, zero-trust reverse proxy, privileged access management, and an identity-aware AI gateway under a single identity and policy model. Whether deployed on-premises using a lightweight user-space connector or managed via Pangolin Cloud, it gives organizations transparent, auditable, and frictionless control over their entire digital footprint.

Stop managing networks. Start managing access.

Keep reading