# Node2Shell: How We Secured Node.js Runtimes and Deployments

Source: https://forgeone.solutions/en/inside-forgeone/node2shell-nodejs-brotli-vulnerability-patch-management
Language: en
Published: 2026-10-26
Updated: 2026-10-27

CVE-2026-111497 affects the Brotli decoder bundled with Node.js. We explain the risk, the fixed releases and how ForgeOne updated and verified runtimes, builds and active services.

On 21 October 2026, the Node.js project published security updates for the supported 22, 24 and 26 release lines. Public discussion has focused on CVE-2026-111497, commonly called “Node2Shell”: a memory-safety flaw in the Brotli decoder shipped with Node.js. Processing specially crafted compressed data can lead to a process crash, disclosure of process memory or code execution.

Operationally, this cannot be resolved by updating a single application dependency. The affected decoder is part of the Node.js runtime. The relevant questions are which Node version produces a build, which version is installed on the target and which binary the active process is actually running.

## What Node2Shell is

Brotli is a compression format used for HTTP content among other purposes. According to the [Node.js security advisory](https://nodejs.org/en/blog/vulnerability/october-2026-security-releases), invalid Brotli input can make the decoder write beyond an internal buffer. Not every Node.js application is automatically exploitable: an untrusted Brotli stream must reach decompression through `node:zlib`. Where that path exists, however, the issue sits below application logic in process memory.

Such a path can arise when configured middleware decompresses a compressed request body or when an application processes a Brotli-compressed response from another service. A basic Node.js HTTP server does not decompress an inbound Brotli body merely by receiving it. Actual reachability depends on frameworks, middleware, proxy configuration and application code; inbound and outbound processing must be assessed separately. This exposure analysis does not replace the runtime update.

## Fixed Node.js releases

The Node.js project lists the following security releases for the affected supported lines:

- Node.js 22: at least 22.23.4
- Node.js 24: at least 24.22.1
- Node.js 26: at least 26.12.1

The release also fixes further vulnerabilities in DNS resolution, TLS hostname verification, HTTP connection reuse, random values in snapshots and the Permission Model. A narrow Brotli workaround is therefore not equivalent to installing the full security release.

## What ForgeOne did

We separated the response into three layers: managed target versions, newly produced artefacts and the active runtime. This matters because changing a version file does not secure a running service by itself.

### The three layers of a runtime patch

1. **Target state**: Managed Node.js versions, runtime baselines and requirements for CI and deployment.
2. **Delivered runtime environment**: Build or release artefact, container image or separately installed runtime and a controlled rollout.
3. **Actually running process**: Active Node.js runtime, version verification, health checks and operational monitoring.

**An updated target state is not evidence that the production process has been updated.**

### 1. Raised Node.js 24 baselines to 24.22.1

The centrally managed runtime definitions for ForgeOneCMS, Nuxt-based Shopware frontends, OpenSchedule and the XWiki frontend we operate were pinned to Node.js 24.22.1. The ForgeOneCMS container base now uses the fixed Node 24 release as well. This prevents future installations and deployments from silently selecting an older 24.x build.

### 2. Rebuilt and deployed applications

The required action depends on the deployment model. A container image that includes Node.js must be rebuilt from a corrected base and redeployed. For standalone artefacts and deployment packages, operators must determine whether the runtime is bundled or provided separately. Where Node.js is installed independently, updating that runtime and then restarting the service in a controlled way may be sufficient. CI and build environments also need their own verified version, even when production uses a separate runtime.

For the inventoried ForgeOne services, we produced the affected container and release artefacts with the corrected runtime, rolled them out in a controlled way and restarted the services. This moved the change beyond managed configuration into the processes handling requests.

### 3. Verified active processes directly

After deployment, we checked the Node version through the executable used by the active systemd processes. The identified production ForgeOneCMS instances and both the German and international Talheim Records Nuxt storefronts were running Node.js 24.22.1 at the time of verification. This statement deliberately covers the services we inventoried and checked.

### 4. Followed with functional and operational checks

A security update is complete only when the service is stable again. Service status, health checks, central web journeys and logs are therefore part of validation. Regular monitoring remains active so that post-deployment faults do not depend on user reports for detection.

## Why npm update is not enough

CVE-2026-111497 is in the Brotli code bundled with the Node.js runtime. `npm update` or a refreshed lockfile may update application dependencies, but it does not necessarily replace the Node binary. Likewise, changing a container base declaration has no effect until the image is rebuilt and the running container is replaced.

A defensible verification answers the following questions:

- Which Node.js version is intended for development, CI and production?
- Does the release artefact bundle the runtime, or is Node.js provided separately?
- Was an artefact with a bundled runtime actually rebuilt after the version change?
- Was the service or container restarted with the new artefact?
- Which version is the active process really using now?

## Monitoring and context

The name “Node2Shell” makes the issue memorable, but it is not a substitute for exposure analysis. Logs may reveal crashes, unusual request patterns or unexpected process execution. They cannot, by themselves, prove that a memory-safety flaw was never triggered. Our response is therefore based on the vendor update and active-runtime verification, not on an assumption that no alert means no risk.

We use automated deployment definitions and controlled rollouts to make changes repeatable. Related background is available on our pages about [Ansible](https://forgeone.solutions/en/products/ansible), [Wazuh](https://forgeone.solutions/en/products/wazuh) and [testing changes in the lab](https://forgeone.solutions/en/inside-forgeone/why-we-test-changes-in-the-lab-first).

## What operators should verify now

- Inventory production, internal and CI Node.js runtimes.
- Update supported lines to 22.23.4, 24.22.1 or 26.12.1 and later.
- Rebuild containers and standalone artefacts when they include the Node.js runtime.
- After a runtime update or deployment, restart affected services in a controlled way or replace containers with the corrected runtime, then verify the Node.js version used by the active process.
- Trace inbound and outbound Brotli paths across frameworks, middleware and proxies.
- Check health endpoints, central user journeys and logs after deployment.
- Replace unsupported Node.js releases because they do not receive regular security updates.

## Verify the active Node.js runtime under systemd

The output of node --version in an interactive shell does not necessarily match the runtime used by the active service. For a direct systemd process, the executable used by its main process can first be identified with:

```bash
PID=$(systemctl show -p MainPID --value my-service.service)
readlink -f "/proc/$PID/exe"
```

The resulting path must be attributed to the correct process and the real runtime version must then be checked. If systemd starts only a wrapper, shell script or process manager, the actual Node.js child process may need to be inspected. For containers, verification takes place inside the running instance. A file path is therefore no more a universal proof than the output from an arbitrary interactive shell.

## Conclusion

Node2Shell demonstrates why runtime patch management is more than package maintenance. Inventory, explicit target versions, reproducible builds, controlled rollouts and active-process verification must align. We completed that chain for the inventoried ForgeOneCMS and Nuxt services on Node.js 24.22.1.

## Frequently asked questions about Node2Shell

### Is every Node.js application immediately exploitable from the internet?

No. The application must decompress attacker-controlled Brotli data. Whether that is possible depends on the application’s data paths. Because the flaw is in the runtime and reachability can change, affected supported release lines should still be updated.

### Can a web application firewall replace the update?

No. Filtering and proxy rules may reduce exposure, but they are not equivalent to the corrected decoder. Variations in data paths, encodings and internal processing make a filtering-only approach incomplete.

### Is node --version showing 24.22.1 sufficient?

No. An interactive shell may use a different binary from the active service. For a direct systemd process, the executable used by its main process can first be identified with the commands shown above. If systemd starts a wrapper, shell script or process manager, the actual Node.js child process may need to be inspected. For containers, verification takes place inside the running instance.

## Hero image

[![Technical illustration of a protected server process intercepting malformed compressed data before processing.](https://forgeone.solutions/media/node2shell-security-operations-hero.webp)](https://forgeone.solutions/media/node2shell-security-operations-hero.webp)

## Author

Mathias Rumbold

## Category

- [Inside ForgeOne](https://forgeone.solutions/en/inside-forgeone/node2shell-nodejs-brotli-vulnerability-patch-management?category=inside-forgeone)

## Tags

- [Inside ForgeOne](https://forgeone.solutions/en/inside-forgeone/node2shell-nodejs-brotli-vulnerability-patch-management?tags=inside-forgeone)
- [Linux Security](https://forgeone.solutions/en/inside-forgeone/node2shell-nodejs-brotli-vulnerability-patch-management?tags=linux-security)
- [Vulnerability Management](https://forgeone.solutions/en/inside-forgeone/node2shell-nodejs-brotli-vulnerability-patch-management?tags=vulnerability-management)
- [Patch management](https://forgeone.solutions/en/inside-forgeone/node2shell-nodejs-brotli-vulnerability-patch-management?tags=patch-management)
- [Security](https://forgeone.solutions/en/inside-forgeone/node2shell-nodejs-brotli-vulnerability-patch-management?tags=security)
- [Operations](https://forgeone.solutions/en/inside-forgeone/node2shell-nodejs-brotli-vulnerability-patch-management?tags=betrieb)

## Links and sources

- [Node.js: 21 October 2026 Security Releases](https://nodejs.org/en/blog/vulnerability/october-2026-security-releases)
- [Node.js v24.22.1 release](https://nodejs.org/en/blog/release/v24.22.1)
- [CVE record CVE-2026-111497](https://www.cve.org/CVERecord?id=CVE-2026-111497)
- [Imperva: Technical reproduction of Node2Shell](https://www.imperva.com/blog/node2shell-from-brotli-data-to-remote-code-execution/)
- [Node.js release schedule](https://github.com/nodejs/Release#release-schedule)

## Node.js security updates must reach the active process

ForgeOne supports inventory, reproducible builds, controlled rollouts, monitoring and technical verification.

[Discuss operations](https://forgeone.solutions/en/contact)

## Further content

- [PHP2Shell: Why Continuous Maintenance, Monitoring and ITSM Make the Difference](https://forgeone.solutions/en/inside-forgeone/php2shell-php-security-monitoring-itsm-maintenance)
