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, 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
Target state: Managed Node.js versions, runtime baselines and requirements for CI and deployment.
Delivered runtime environment: Build or release artefact, container image or separately installed runtime and a controlled rollout.
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, Wazuh and testing changes in the lab.
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:
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?Show answerHide answer Action: Open answerClose answer
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?Show answerHide answer Action: Open answerClose answer
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?Show answerHide answer Action: Open answerClose answer
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.







