Node.js Brotli Vulnerability: How Applications Become Exposed and What Developers Should Check

CVE-2026-111497: a Brotli decoder flaw in Node.js. How apps become exposed, what Imperva showed, and what to check before patching.

Read in: English · తెలుగు · हिन्दी

Sign in to save

Cover graphic. The same Brotli-compressed data (br) enters the Node.js decoder twice, under the labels CVE-2026-111497 and High. On the vulnerable Node.js 24.22.0 the data overruns the decoder's eight-byte internal buffer and, in Imperva's test, code ran (RCE). On the fixed Node.js 24.22.1 the same data is rejected as an invalid format.

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.

The first fixed Node.js release for each supported line
Node.js release lineSecurity release
22.x LTS22.23.4
24.x LTS24.22.1
26.x Current26.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.

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

  1. Vendor advisory and fix (current step)
  2. Proof of concept in a tested build
  3. Reliable across environments
  4. Confirmed 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.

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:zlib Brotli 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.

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.

The other security areas fixed in the same release
Security areaRelevant findingsWhy teams should care
TLS certificate validationCVE-2026-105483, CVE-2026-106069, CVE-2026-106072Certain non-standard representations of IP addresses can lead to incorrect certificate identity matching under specified conditions.
DNS resolutionCVE-2026-105482Hostnames containing NUL characters (zero bytes) can be truncated during resolution, creating differences between validated and resolved names.
Cryptographic randomnessCVE-2026-106074Certain 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 reuseCVE-2026-105481Under particular timing conditions, an HTTP client can associate an unsolicited response with a later request.
ZIP processingCVE-2026-106070In Node.js 26.x, a ZIP validation failure can cause unexpected attacker-controlled bytes to be returned.
Filesystem Permission ModelCVE-2026-106071, CVE-2026-106073Specific 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

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

Report a correction

Corrections go to the editor and are never published automatically. No account needed.