TechiesJournal illustration of the vulnerability. The same malformed compressed data is handled differently by the vulnerable and the fixed Node.js decoder.
A critical part of an application’s security can sit inside code its developers never directly touch. The October 2026 Node.js security releases show why understanding runtime behaviour matters as much as updating application dependencies.
A compressed API response can reach native code
Imagine a Node.js service that retrieves information from an external API. The application makes an ordinary HTTP request, receives a compressed response and processes the returned data. Nothing about that workflow appears unusual.
Between receiving the response and using its contents, the runtime may need to decompress it. If the response uses Brotli, that work reaches a decoder implemented in native code. Suppose the compressed data is deliberately malformed and the decoder handles it incorrectly.
That is the security problem behind CVE-2026-111497, a high-severity vulnerability disclosed as part of the Node.js security releases on October 21, 2026. The flaw can cause the Brotli decoder bundled with Node.js to write outside an internal memory buffer. According to the official Node.js advisory, the consequences may include process crashes, memory disclosure or remote code execution. Researchers at Imperva subsequently demonstrated code execution using crafted Brotli data against an official vulnerable Node.js build.
For developers and engineering teams, the important question is not simply whether their application uses Node.js. It is whether untrusted compressed data can reach the vulnerable decoder, and whether the Node.js version actually running in their environment has been patched.
Node.js shipped ten security fixes on October 21
On October 21, the Node.js project released security updates for three supported release lines. The 22.x and 24.x lines are long-term-support (LTS) releases, and 26.x is the Current line.
| Node.js release line | Security release |
|---|---|
| 22.x LTS | 22.23.4 |
| 24.x LTS | 24.22.1 |
| 26.x Current | 26.12.1 |
The announcement addressed ten CVEs across memory safety, TLS certificate validation, DNS handling, cryptographic randomness, HTTP connection reuse, ZIP handling and filesystem permissions. It also updated bundled dependencies, including c-ares, OpenSSL, SQLite, Undici and the CA certificate store. The highest severity classification assigned by the Node.js project was High. The Hong Kong Computer Emergency Response Team Coordination Centre also published a security bulletin on October 22, recommending updates to the fixed versions.
One vulnerability stands out because of its possible consequences and the subsequent technical evidence: CVE-2026-111497, involving the Brotli decoder. The rest of the security release matters too, so teams should apply the complete update rather than trying to address only one vulnerability.
Brotli is a compression format built into Node.js
When a server sends information over a network, compression can reduce the amount of data transferred. An API response containing repetitive text may need fewer bytes when compressed, and the receiving application decompresses it to recover the original information. Brotli is one of the compression formats used for this purpose, and it is commonly identified by the HTTP content encoding br.
Node.js includes Brotli compression and decompression through its node:zlib module. Applications can reach that functionality directly, or indirectly through components that process compressed data. A developer might never write code that explicitly calls a Brotli decompression function, yet the application may still use one through HTTP response handling or request-body middleware. Middleware is code that processes a request before the application’s own handler sees it.
The vulnerability exists inside the decoder, not in the application’s business logic.
An invalid block switch let the decoder write past its buffer
A decoder processes compressed data according to rules defined by the compression format. As it reads the input, it tracks the state of the compressed stream, including which blocks and block types are valid at a particular point. If the stream contains an invalid transition, the decoder should reject it.
The vulnerable Brotli decoder did not always make that distinction correctly. According to the Node.js advisory, an invalid block switch could be treated as though the decoder simply needed more input. Instead of returning a permanent format error, processing could continue. That incorrect state handling allowed the streaming decoder to keep appending bytes to an eight-byte internal buffer beyond its intended boundary.
This is an out-of-bounds write: a program writes data beyond the memory region intended to hold it. Such a defect can corrupt process memory. Depending on the circumstances, the consequences may range from a crash to more serious security compromise. The Node.js advisory credits OpenAI Codex Security researchers Khai Tran and Sylvie Mayer with reporting the flaw.
The upstream Brotli correction changes the way decoder functions identify and propagate invalid-format errors. An impossible block transition is reported as an error rather than being confused with a request for additional input. In practical terms, the fix restores an important boundary: invalid compressed data must not cause the decoder to continue processing in an unsafe state.
This does not mean that every malformed Brotli response will result in code execution. The issue is that a particular class of malformed input can reach vulnerable memory-handling behaviour.
Two routes can carry untrusted Brotli data to the decoder
There are at least two important paths to understand.
A service receives a compressed HTTP response
Consider a backend service that retrieves data from a third-party API using Node.js’s built-in fetch(). The remote server may return a response compressed using Brotli. When the client processes that response, the decoding operation can reach the Brotli implementation bundled with Node.js. If an attacker can control the compressed data returned to the application, the decoder becomes a potential attack surface.
This does not mean that every use of fetch() is automatically exploitable. The application must encounter relevant compressed input, and the vulnerable decoding path must be reached. It does show why an outbound HTTP request can be security-relevant. Developers often focus on protecting incoming requests because that is where external users interact with their applications, but responses from external services are also data crossing a trust boundary.
A service decompresses an incoming request body
The second path involves request-body processing. Applications built using Express may configure middleware to parse incoming JSON, text or raw request bodies, and some parser configurations can decompress Brotli-encoded bodies before passing their contents to application code. In that situation, a client supplying a crafted compressed request body may be able to reach the same vulnerable decoder.
A basic Node.js HTTP server does not automatically decompress every Brotli request body merely because it receives one. The relevant processing must be enabled through middleware or application code. That is why reviewing the actual request-processing path matters more than assuming that every Express or Node.js application has identical exposure.
Two routes to the Brotli decoder
Select a route to see how untrusted compressed data can reach the decoder and what that does and does not mean.
Consumed HTTP response
What happens
- A service fetches data with built-in fetch() and receives a Brotli-compressed response.
- Decoding that response can reach the bundled decoder, so data from an external server crosses a trust boundary.
What it does not mean
- That every use of fetch() is exploitable.
- That an application is exposed when the attacker cannot control the compressed input it decodes.
Incoming request body
What happens
- Middleware such as Express 5 request parsers can be configured to decompress Brotli-encoded bodies.
- A client supplying a crafted compressed body may then reach the same decoder.
What it does not mean
- That Express is the source of the flaw.
- That every Express application decompresses Brotli request bodies.
Bare HTTP server
What happens
- A basic Node.js HTTP server does not decompress a Brotli request body just because it receives one.
What it does not mean
- That the application is safe if other code or middleware decompresses data.
- That the runtime needs no update.
Both routes end in the same native decoder bundled with Node.js, so the fix is in the runtime, not in either route.
Imperva demonstrated code execution in a tested build
On October 22, Imperva Threat Research published an analysis by Ron Masas called Node2Shell: From Brotli Data to Remote Code Execution. Its researchers tested crafted Brotli data against applications running the official Node.js 24.22.0 Linux arm64 image. They reported successful code execution in two application scenarios: a service consuming a compressed HTTP response through built-in fetch(), and applications processing incoming Brotli-compressed request bodies using selected Express 5 and body-parser 2 configurations.
The tests used a marker file to demonstrate that code supplied with the malicious compressed data had executed inside the application process. Importantly, Imperva reported that the same inputs were rejected by Node.js 24.22.1, without the marker file being created.
The researchers also disclosed meaningful limitations. Their proof of concept did not succeed on every attempt, and they did not test every Node.js build or application configuration. These results support a specific conclusion: remote code execution was demonstrated in the tested environment using an official vulnerable Node.js build. They do not establish that code execution is reliable across all vulnerable environments, or that attackers have already compromised production applications.
A working proof of concept and confirmed exploitation in the wild are different forms of evidence. As of the sources reviewed for this article on October 23, 2026, confirmed active exploitation in real-world attacks has not been established.
How far the evidence goes
Select a step to see what that kind of evidence establishes and what it does not.
1. Advisory and fix
- 1Vendor advisory and fix (current step)
- 2Proof of concept in a tested build
- 3Reliable across environments
- 4Confirmed attacks in the wild
What it shows
- Node.js documents the flaw, rates it High and ships fixes in 22.23.4, 24.22.1 and 26.12.1.
What it does not show
- That any attacker has used it.
2. Proof of concept
- 1Vendor advisory and fix
- 2Proof of concept in a tested build (current step)
- 3Reliable across environments
- 4Confirmed attacks in the wild
What it shows
- Imperva ran code through crafted Brotli data on the official Node.js 24.22.0 Linux arm64 image and saw the same input rejected by 24.22.1.
What it does not show
- That it works on every attempt, platform or configuration.
3. Reliable everywhere
- 1Vendor advisory and fix
- 2Proof of concept in a tested build
- 3Reliable across environments (current step)
- 4Confirmed attacks in the wild
What it shows
- Not established. Imperva did not test every build or application.
What it does not show
- That all Node.js applications are exploitable.
4. Attacks in the wild
- 1Vendor advisory and fix
- 2Proof of concept in a tested build
- 3Reliable across environments
- 4Confirmed attacks in the wild (current step)
What it shows
- Not established in the sources reviewed on October 23, 2026.
What it does not show
- That production applications have not been attacked, or that patching can wait.
As of the sources reviewed on October 23, 2026, the first two are established. The last two are not.
Express is a route to the decoder, not the cause
Using Express does not by itself make an application vulnerable. Express applications can have very different request-processing configurations. Some endpoints parse compressed bodies, while others may never invoke Brotli decompression.
Imperva tested selected configurations involving Express 5 and body-parser 2, and its findings demonstrate that these components can expose a route into the affected Node.js decoder. Express was not the underlying source of the memory-safety defect, and that distinction determines the proper remediation. Changing a middleware configuration may help reduce exposure to particular inputs, but it does not repair the vulnerable decoder inside an older Node.js runtime.
The primary fix is updating Node.js.
Teams should still review middleware and request-body handling because those components help determine where untrusted compressed data enters the application.
A firewall may not cover the outbound path
A web application firewall (WAF) can inspect and sometimes block malicious incoming HTTP traffic. That can provide useful protection against certain attack paths, particularly when the vulnerable operation involves request bodies entering a public service.
Consider the earlier example of a Node.js application making an outbound request. An inbound firewall protecting the application’s public endpoints does not necessarily inspect the compressed response returned by an external API, so the decoder can still receive untrusted data through that different route. Imperva reports deploying WAF rules for exploitation attempts it reproduced, while also recommending that customers update their Node.js runtimes.
These controls serve different purposes. A firewall rule may reduce exposure to known malicious traffic, while a runtime security update corrects the underlying vulnerability. Temporarily limiting untrusted Brotli traffic on affected paths, as Imperva suggests, or filtering other traffic may be useful while updates are deployed, provided teams understand the effect on normal application behaviour. They should not be treated as a permanent substitute for patching.
Check the running version, the data paths and the deployed artifacts
The immediate priority is establishing which Node.js runtime versions are actually deployed.
Check the running Node.js version
On a host or development environment:
node --version
For a running Docker container:
docker exec <container-name> node --version
For a locally available container image:
docker run --rm --entrypoint node <image-name> --version
The last command assumes the image can be run with that entry point and that the Node.js executable is available on the container’s executable search path. These checks identify the version of the Node.js executable being invoked. They do not, by themselves, prove the entire application is secure.
Review where compressed data is processed
Teams should identify applications that decompress external data, particularly through:
- Node.js
node:zlibBrotli APIs - built-in
fetch()calls consuming compressed responses - request-body middleware configured to decompress incoming bodies
- other packages or components that ultimately use the bundled decoder
This review helps prioritize exposure investigation. It should not delay installing the available security updates.
Inspect deployed artifacts, not only source files
A repository may specify a recent Node.js version while an older version remains inside a deployed container image. Similarly, a build pipeline might have been updated without rebuilding all the application images derived from an older base image. For containerized systems, the remediation process should include rebuilding affected images, deploying them and verifying the Node.js version inside the running containers.
For managed runtimes and serverless services, teams should confirm the runtime version and patch status supplied by their provider rather than assuming that every environment has already been updated. If an application still runs an unsupported Node.js version, the appropriate remediation may require moving to a supported release line.
Where to check the Node.js version
Select where the application runs to see what to check and what to confirm.
Host
What to check
- Run node –version on the host or development environment.
What to confirm
- That the executable you invoked is the one the service actually uses.
Running container
What to check
- Run docker exec with the container name and node –version.
What to confirm
- That the version inside the running container is a fixed release.
Container image
What to check
- Run docker run –rm –entrypoint node with the image name and –version, if the image allows that entry point.
What to confirm
- That images derived from an older base image were rebuilt and redeployed.
Managed or serverless
What to check
- Read the runtime version and patch status your provider supplies.
What to confirm
- Provider confirmation, rather than an assumption that it was already updated.
Unsupported version
What to check
- Plan a move to a supported release line.
What to confirm
- The target release: 22.23.4, 24.22.1, 26.12.1 or newer.
The version in source control is the intended version. The version in the running artifact is the one that matters.
Test the application after upgrading
A runtime security update can affect application behaviour, particularly when network processing, dependencies or native components change. Teams should run their normal regression tests, verify essential HTTP integrations, and confirm that request parsing and decompression still behave correctly for valid inputs. Security patching should be prompt, but deployment should still be controlled and verifiable.
The same release fixed nine other vulnerabilities
The Brotli issue is the main focus of this article, but the October release addressed a broader set of security concerns. The other findings are relevant because they affect assumptions that developers and platform teams may make about runtime behaviour.
| Security area | Relevant findings | Why teams should care |
|---|---|---|
| TLS certificate validation | CVE-2026-105483, CVE-2026-106069, CVE-2026-106072 | Certain non-standard representations of IP addresses can lead to incorrect certificate identity matching under specified conditions. |
| DNS resolution | CVE-2026-105482 | Hostnames containing NUL characters (zero bytes) can be truncated during resolution, creating differences between validated and resolved names. |
| Cryptographic randomness | CVE-2026-106074 | Certain startup snapshots and single executable applications (self-contained packaged programs) can preserve entropy caches, which are stored random values, causing values expected to be unique or unpredictable to repeat across processes. |
| HTTP connection reuse | CVE-2026-105481 | Under particular timing conditions, an HTTP client can associate an unsolicited response with a later request. |
| ZIP processing | CVE-2026-106070 | In Node.js 26.x, a ZIP validation failure can cause unexpected attacker-controlled bytes to be returned. |
| Filesystem Permission Model | CVE-2026-106071, CVE-2026-106073 | Specific path-matching and filesystem API behaviours can bypass intended permission restrictions. |
These vulnerabilities do not all have the same prerequisites, severity, consequences or affected release lines. According to the advisory, CVE-2026-105483 affects 26.x and 24.x, the ZIP issue CVE-2026-106070 and the filesystem wildcard issue CVE-2026-106071 affect 26.x only, and the others affect all three lines. For example, the randomness issue requires particular snapshot-related behaviour. It is not evidence that every call to crypto.randomUUID() produces predictable values. Likewise, the TLS issues involve specific hostname representations and certificate-validation conditions, and they should not be described as a general failure of TLS encryption.
The official Node.js advisory gives the individual affected release lines and technical conditions. Engineering teams should consult those details when investigating their own exposure.
Application security extends into the runtime
A developer may write careful application code, validate inputs and keep application dependencies updated. Those practices remain necessary, but applications also depend on the behaviour of the runtime beneath them. An HTTP client may decompress data. A TLS library may interpret a hostname. A DNS resolver may transform a name. A cryptographic API may rely on state created during application startup. Each of those operations can affect a security decision.
The October Node.js vulnerabilities illustrate several ways that low-level behaviour can undermine assumptions made at higher layers of an application. The Brotli issue provides a particularly concrete example because researchers demonstrated a path from ordinary compressed HTTP data to code execution in a tested Node.js environment. That does not make every Node.js application exploitable. It does demonstrate why teams must understand which runtime capabilities their applications actually use.
The recent PHP2Shell vulnerabilities discussed by TechiesJournal offer a related lesson from another runtime, although the underlying technical mechanisms and exposure conditions differ. For both ecosystems, secure application code alone cannot compensate for an unpatched memory-safety flaw in the runtime that executes it.
The immediate steps are to patch, map and verify
The immediate action is straightforward: identify affected Node.js deployments and move them to the applicable fixed releases, which are 22.23.4, 24.22.1 or 26.12.1, or to newer supported releases containing the fixes. At the same time, developers and security teams should identify where untrusted compressed data reaches runtime decompression functions, including through outbound HTTP responses and configured request-body middleware. Infrastructure teams should verify the runtime actually deployed in containers, hosts and managed environments, rather than relying only on intended versions in source-control configuration.
If evidence of suspicious behaviour exists, investigate it using application logs, runtime information and relevant security telemetry. A process crash or decompression error alone is not proof of compromise. There is no need to assume that every Node.js application has been attacked. There is also no sound reason to delay an available runtime security update simply because public evidence of widespread exploitation has not emerged.
The main lesson is broader than Brotli.
Applications inherit security boundaries from their runtimes. Knowing where untrusted data crosses those boundaries is part of understanding the application’s real attack surface.
Go deeper
Research reviewed October 23, 2026. Threat activity, patch availability and vendor guidance can change quickly, so check the primary sources before acting.
Vendor, researcher and government sources
- Node.js, October 21, 2026 Security Releases, Node.js Project, October 21, 2026, the primary advisory covering all ten CVEs, the affected release lines, technical descriptions and released fixes.
- Node2Shell: From Brotli Data to Remote Code Execution, Imperva Threat Research, October 22, 2026, details of the reported code-execution experiments, tested Node.js build, request and response exposure paths, patch comparison and limitations.
- Detect and Report Invalid Stream Earlier, Google Brotli upstream source commit, code-level evidence of the changes to decoder error handling.
- Node.js Multiple Vulnerabilities, Hong Kong Computer Emergency Response Team Coordination Centre, October 22, 2026, an additional security bulletin summarizing the impact and recommended security releases.
This article distinguishes vendor advisories, reported experimental findings and practical engineering recommendations. Deployment-specific exposure and later threat activity should be reassessed before acting.
Related reading on TechiesJournal
- Critical PHP Vulnerabilities: Who Is Affected, What Could Happen, and How to Patch Safely, TechiesJournal, October 2026, the related runtime vulnerability in PHP and how to patch it safely.
- Node.js, Docker and Go: Three Quiet Changes That Can Break Your Pipeline, TechiesJournal, October 2026, for other Node.js runtime and container changes that affect delivery pipelines.
