
Most Node.js services decompress data they did not create. A browser sends a compressed request body. An API client fetches a compressed response from a partner, a webhook target or a user-supplied URL. Node.js handles that decompression quietly, inside the runtime, and almost no one treats it as an attack surface. CVE-2026-111497 changes that: an out-of-bounds write in the Brotli decoder bundled with Node.js permits remote code execution when a crafted Brotli stream is decompressed.
The Node.js project released fixes on 21 October 2026 across all three supported lines: 26.12.1, 24.22.1 and 22.23.4. The same release fixes nine further CVEs, including three high-severity flaws that let an attacker get past TLS hostname checks or DNS name validation. For ANZ organisations running Node.js in production, the work is the same as any runtime vulnerability: find every Node.js runtime, patch it, restart it, and keep the record that APRA CPS 234 supervisors, SOC 2 auditors and ISO 27001 certification bodies will ask for.
Part One: The Brotli Decoder RCE (CVE-2026-111497)
CVE-2026-111497 is rated high severity by the Node.js project, which states that the out-of-bounds write permits remote code execution. It affects every supported release line: 22.x, 24.x and 26.x.
Where the Flaw Lives
The bug sits in the Brotli library that Node.js bundles from upstream (google/brotli), not in Node.js's own JavaScript code. A crafted stream that declares a single block type and then switches blocks was not rejected. The decoder wrote past the end of a buffer instead. The fix makes the decoder stop with an error on streams shaped this way.
Because the library ships inside the Node.js binary, updating npm packages does nothing. The runtime itself must be replaced.
Which Code Paths Reach It
Any code that decompresses Brotli data an attacker can influence is in scope:
- Direct zlib calls:
zlib.brotliDecompress,zlib.brotliDecompressSyncandzlib.createBrotliDecompress, in both one-shot and streaming use. - Built-in fetch: for HTTPS URLs, Node.js's fetch advertises Brotli support by default and decodes Brotli responses through zlib. A malicious or compromised server can return a crafted response.
- Servers accepting compressed bodies: any API or body parser that decompresses
Content-Encoding: brrequest bodies. - Proxies and gateways: anything that decompresses responses from servers it does not control.
The highest-risk pattern is a service that fetches a URL a user supplies: link previews, webhook delivery, image or document importers, and server-side rendering that pulls remote content. In each case, the attacker chooses the server, and the server chooses the bytes.
Exploitation Status
As of 22 October 2026, no public technical write-up exists, and no exploitation has been reported. The fix was developed privately. That window rarely stays open. The patch itself shows where the bug is, and a crafted-stream bug in a widely deployed decoder is an attractive target.

Part Two: The Other Nine CVEs
The Brotli RCE takes the headlines, but three more high-severity flaws in the same release undermine checks that most teams treat as solved: TLS hostname checks and DNS name validation.
TLS Hostname Bypasses (CVE-2026-106069, CVE-2026-105483)
Node.js normalised hostnames before checking them against a certificate, then connected using the original form. An address such as 0127.0.0.1 could be checked as one address and connected to as another (CVE-2026-106069). CVE-2026-105483 does the same with fullwidth digits that only become an IP address after normalisation. A related medium-severity flaw, CVE-2026-106072, is listed with the other medium findings below.
The exposure is in services that open TLS connections to hosts an attacker can influence: webhooks, link previews, outbound proxies and integrations configured by customers.
DNS Name Truncation (CVE-2026-105482)
dns.resolve and related calls passed names to the c-ares library as C strings, so a NUL byte ended the name early. A value such as example.com\0.trusted.corp passes a JavaScript endsWith('.trusted.corp') check but resolves example.com. Allow-list checks built on string matching fail silently. dns.lookup is not affected.
The Remaining Medium and Low Findings
| CVE | Severity | What it means |
|---|---|---|
| CVE-2026-105481 | Medium | A malicious server could pre-load a response onto an idle keep-alive socket, and the client would accept it as the answer to its next request. |
| CVE-2026-106072 | Medium | A certificate issued for a DNS name such as 127.0.0.1 could authenticate non-canonical forms of that IPv4 address. Fixed by the same change as CVE-2026-106069. |
| CVE-2026-106074 | Medium | crypto.randomUUID() and randomInt() caches could be saved into startup snapshots and single executable applications, so separate processes repeated the same values. |
| CVE-2026-106070 | Low | The experimental zlib.ZipFile (26.x only) could return attacker-controlled bytes after a failed header check. |
| CVE-2026-106071 | Low | Wildcard paths in the Permission Model could grant broader file access than intended (26.x only). |
| CVE-2026-106073 | Low | fs.realpathSync() skipped a Permission Model check that related functions perform. |
CVE-2026-106074 deserves attention from any team that ships Node.js as a single executable or uses startup snapshots. UUIDs, tokens and random values generated by affected binaries should be treated as predictable, and any secrets derived from them rotated.
The release also updates bundled c-ares, Undici, OpenSSL (22.x and 24.x), SQLite (22.x) and the CA certificates. The Node.js security post lists the certificate update as "eMudhra Intermediate CA Compromise", and the release notes describe the change as rejecting certificate chains that contain blocked public keys.

Part Three: Who Is Affected
Every supported Node.js release line is affected, and no fix is coming for end-of-life lines. The Node.js project states that end-of-life versions are always affected when a security release occurs. The question is not whether your application code is secure. It is which Node.js binary runs it.
| Release Line | Status | Fixed In |
|---|---|---|
| 26.x (Current) | Vulnerable below 26.12.1 | 26.12.1 |
| 24.x (LTS) | Vulnerable below 24.22.1 | 24.22.1 |
| 22.x (LTS) | Vulnerable below 22.23.4 | 22.23.4 |
| 20.x and older | End of life (ended 30 April 2026) | No fix. Migrate to 22.x or 24.x immediately. |
Where Node.js Hides
Node.js rarely runs in one place. A complete inventory covers:
- API servers, BFF layers and server-side rendering (Next.js, Nuxt, Remix)
- Serverless functions such as AWS Lambda, Azure Functions and Google Cloud Functions
- Container images built
FROM node:at an old tag - Electron desktop apps, which bundle their own Node.js runtime
- CI runners, build tooling and internal scripts that fetch remote content
- Vendor appliances and SaaS agents shipped as single executable applications
Cloud Platforms Are Not Patched at the Same Time
The official node Docker images were updated on 21 October 2026, and AWS published patched Lambda base images in the early hours of 22 October UTC. As of 22 October, AWS Elastic Beanstalk and Amazon Linux packages were not yet fixed. AWS stopped patching the nodejs20.x Lambda runtime on 30 April 2026, so functions still on Node.js 20 will not receive this fix at all.
A managed runtime that shows a recent deployment date is not proof of a patched runtime. Check the actual Node.js version each workload reports with node -v or process.version.

The Node.js Service You Forgot Is the One That Fetches URLs
Link previews, webhooks and importers are exactly where a hostile server can reach your runtime. See every internet-facing asset in your organisation before an attacker does.
Part Four: The Response Plan
Upgrading the runtime is the only complete fix. The Node.js project has published no workaround for the Brotli RCE, and interim measures only narrow specific paths.
Step One: Inventory Every Node.js Runtime
Start with services that are internet-facing or that fetch content from addresses users or customers control. For each workload, record the Node.js version it actually reports, how it is deployed (container, serverless, VM, desktop app), and who owns it. Workloads on Node.js 20 or older go on a separate list: they need a migration plan, not a patch.
Step Two: Upgrade, Rebuild and Restart
- Move each workload to 26.12.1, 24.22.1 or 22.23.4.
- Rebuild container images from an updated base image, and redeploy them. Pin to the patched version rather than a floating tag, so the fix is provable.
- Update serverless functions to a runtime that carries the fixed version, and confirm the version each function reports after deployment.
- Restart every long-running Node.js process. The old binary stays in memory until it does.
- On platforms that have not shipped the fix yet, such as Elastic Beanstalk as of 22 October, track the vendor update and apply the interim measures below.
Step Three: Interim Measures Where Upgrading Must Wait
These reduce exposure to specific paths. None is a fix.
Content-Encoding: br on inbound traffic at the reverse proxy. Removing br from Accept-Encoding on outbound fetch calls only reduces exposure to servers that respect that header; a hostile server can ignore it and send Brotli anyway, so it is not a defence against the attacker this post describes.dns.resolve.--permission as a security boundary for untrusted code on any version.Step Four: Rotate What May Be Predictable
If you ship single executable applications or use startup snapshots, treat UUIDs, tokens and random values generated by affected binaries as predictable. Rebuild on a patched version, then rotate any secrets, session identifiers or keys those binaries produced.

Part Five: What This Release Means for ANZ Compliance Evidence
A runtime security release is a test of process, not just of patching. Auditors and regulators will not ask whether Node.js was upgraded. They will ask how the organisation knew which workloads ran Node.js, when each was upgraded, and how the upgrade was verified.
APRA CPS 234
APRA-regulated entities must maintain information security capability commensurate with the threats they face and test the effectiveness of their controls systematically. A high-severity RCE in a runtime used across APIs, serverless functions and internal tooling is a direct test of that capability. If a vulnerable workload is compromised and the incident is material, the 72-hour notification obligation to APRA applies. The record of identification, remediation and verification is what shows the capability worked.
SOC 2 and ISO 27001
SOC 2 auditors assess vulnerability management under the Common Criteria for system operations. ISO 27001:2022 control A.8.8 requires timely management of technical vulnerabilities. Both look for the same evidence: an inventory showing every Node.js runtime was in scope, dated upgrade records, and verification that each workload now reports a fixed version. End-of-life Node.js 20 workloads need a documented migration plan and compensating controls, because they will never receive this fix.
Why Dependency Scanners Miss This
Software composition analysis tools read package.json and lockfiles. The Brotli decoder ships inside the Node.js binary, so it does not appear in any lockfile. A clean SCA report says nothing about the runtime underneath. Evidence that relies only on dependency scanning will not satisfy an assessor asking about CVE-2026-111497.
The Lesson Beyond This Release
The most dangerous code path in this release is the one teams think of least: decompressing data that arrived from somewhere else. Services that fetch user-supplied URLs turn every hostile server on the internet into a potential attacker. Point-in-time testing scoped a year ago will not have asked whether your link-preview service decompresses Brotli from arbitrary hosts.
Capture The Bug's continuous penetration testing combines expert-led testing with a PTaaS platform that reports validated findings in real time. When a runtime CVE lands, our team identifies which of your exposed services run affected versions, tests the paths that reach the vulnerable code, and retests after remediation, producing the evidence trail APRA CPS 234, SOC 2 and ISO 27001 assessors look for.
Book a rapid Node.js exposure assessment with Capture The Bug to confirm which of your Node.js services are vulnerable, verify that upgrades have taken effect, and document the result for your next audit.
Runtime CVEs Don't Show Up in Your Lockfile
Learn how ANZ organisations move from point-in-time testing to continuous coverage that catches runtime vulnerabilities as they are disclosed.
Frequently Asked Questions
What is CVE-2026-111497?
CVE-2026-111497 is a high-severity out-of-bounds write in the Brotli decoder bundled with Node.js. The Node.js project states that it permits remote code execution. It is triggered when Node.js decompresses a crafted Brotli stream, whether through zlib.brotliDecompress, zlib.createBrotliDecompress, the built-in fetch decoding a Brotli response, or a server decompressing a Content-Encoding: br request body. It affects Node.js 22.x, 24.x and 26.x, and is fixed in 22.23.4, 24.22.1 and 26.12.1, released on 21 October 2026.
Does updating npm packages fix it?
No. The vulnerable Brotli library ships inside the Node.js binary, so it does not appear in package.json or any lockfile. Updating dependencies, running npm audit or rebuilding with the same base image leaves the vulnerable runtime in place. The fix requires a new Node.js binary, delivered through a new container base image, a new serverless runtime, or a new system package, followed by a restart.
Is my application vulnerable if it never calls zlib directly?
Possibly. The built-in fetch asks HTTPS servers for Brotli by default and decodes Brotli responses through zlib, so any service that fetches content from a server an attacker controls can reach the vulnerable decoder without calling zlib directly. Servers and frameworks that decompress Brotli-encoded request bodies are also in scope. Treat any internet-facing Node.js service, or any service that fetches untrusted URLs, as in scope until you have confirmed it never decompresses Brotli from untrusted sources.
We still run Node.js 20. What now?
Node.js 20 reached end of life on 30 April 2026 and will not receive a fix for any of these CVEs. AWS also stopped patching the nodejs20.x Lambda runtime on that date. The only remedy is migrating to Node.js 22 or 24. Until migration is complete, apply the interim measures in this guide, restrict network exposure, and document the risk acceptance and compensating controls for your auditors.
How should ANZ organisations document their response for compliance?
Record four things: the inventory showing every Node.js runtime assessed, including serverless functions and container images; the date each was upgraded and restarted; the evidence used to confirm the fix, such as the version each workload reports after deployment; and the migration plan and compensating controls for any end-of-life workloads. APRA CPS 234 entities should keep this as evidence of information security capability and control testing, and assess whether any confirmed compromise is a material incident requiring notification within 72 hours. SOC 2 and ISO 27001 assessors will look for the same record under vulnerability management controls.




