Contents
ToggleExecutive Summary
On November 11, 2026, Node.js shipped security releases 22.23.5, 24.22.3 and 26.13.1. They fix 16 Node.js vulnerabilities in the runtime itself. Seven are rated High.
Two of them matter most. Both sit in code that every Node.js process runs once it terminates TLS or speaks HTTP/2.
CVE-2026-123864 is a memory leak in the HTTPS request parser. It can hand an attacker TLS private keys and other users’ request data.
CVE-2026-123863 is an assertion failure in HTTP/2 session teardown. One unauthenticated request can abort the process.
Neither bug needs credentials. Neither needs a special protocol extension or an unusual config.
CVE-2026-123863 fires against a default HTTP/2 server whose handler responds before the request body has fully arrived. The Node.js project itself calls this pattern typical.
CVE-2026-123864 needs two things. A handler that flushes headers early and later ends the response with data. And a route that echoes or stores the request body. Both bugs work over TLS and over cleartext.
Node.js runs a big share of internet-facing APIs, CI workers and container workloads. So the attack surface is wide, even though each CVE only fires under certain conditions.
One more detail. Five of the fixed CVEs, including both headline bugs, are credited to security researcher Chris Rohlf, working with Claude and Anthropic Research.
The advisory reports no exploitation in the wild. There is no workaround. If you run a native HTTP/2, HTTPS or TLS listener, upgrading is the only supported fix.
TL;DR for Engineering Teams
What it is. 16 vulnerabilities fixed in Node.js: 7 High, 6 Medium, 3 Low. Start with two. CVE-2026-123864 is an HTTPS heap memory leak that can expose TLS private keys and other connections’ requests (OpenJS CNA CVSS 8.1). CVE-2026-123863 is an unauthenticated HTTP/2 process crash (OpenJS CNA CVSS 8.2).
Where it bites. Any Node.js process that terminates TLS itself or serves HTTP/2 to untrusted clients. CVE-2026-123864 affects the 22.x, 24.x and 26.x lines. CVE-2026-123863 affects 24.x and 26.x. Plain node:http servers are not affected by the HTTPS leak. End-of-life lines like 20.x and 25.x get no fix.
Why it matters. One request crashes a default HTTP/2 server. The HTTPS bug can expose private keys and cross-tenant request data. Both are unauthenticated and reachable over the network. The advisory reports no public proof of concept and no active exploitation. But upstream regression tests for the memory leak bugs are public. So technical reproduction evidence exists.
Patch status. Available. Fixed versions are 22.23.5, 24.22.3 and 26.13.1, released November 11, 2026. There is no workaround for servers that can’t update.
Immediate action. Upgrade reachable native HTTP/2, HTTPS and TLS services to the fixed release for their line. Restart the running processes. Rebuild affected container images. If an HTTPS server matched the CVE-2026-123864 handler pattern, treat TLS key rotation as a separate incident-response decision.

[IMAGE 1: Campaign overview infographic. Prompt in section ⑪, Image 1. Alt text below.]
Vulnerability Overview
| Field | Value |
|---|---|
| Vendor | OpenJS Foundation (Node.js project) |
| Product | Node.js runtime |
| Vulnerability Type | Memory disclosure (CVE-2026-123864); reachable assertion / denial of service (CVE-2026-123863) |
| CWE | CWE-416 Use After Free / CWE-125 Out-of-bounds Read (123864); CWE-617 Reachable Assertion (123863) |
| CVSS Score | 8.1 and 8.2 (OpenJS CNA CVSS 3.0; NVD not yet scored) |
| CVE | CVE-2026-123864, CVE-2026-123863 (plus 14 others in the same release) |
| Patch Available | Yes: 22.23.5, 24.22.3, 26.13.1 |
| Active Exploitation | Not confirmed; no public PoC reported in the advisory |
Technical Anatomy
This release fixes several separate bugs with different root causes. The two top-priority ones live in different subsystems. So we look at each one on its own, then cover the rest of the High-rated set.
Root Cause: CVE-2026-123864 (HTTPS memory disclosure)
This bug lives where the HTTPS request parser meets the TLS write path. HTTP/2 is not involved.
Here’s how it happens. The app flushes response headers before the request body has fully arrived. Later it ends the response with a non-empty chunk. At that point, an empty TLS write can call the parser’s output-clearing routine. JavaScript is still running inside a parser callback when this happens.
That nested run leaves a stale buffer span in play. The parser can then read heap memory the client never sent. If the route echoes or stores the request body, the leaked memory goes back to the attacker. Or it lands in storage the attacker can read later.
The advisory says the leaked memory can belong to other connections. It can include TLS private keys and other users’ requests.
The upstream fix closes both the entry path and the buffer handling. It skips the output-clearing routine for empty writes while a TLS cycle is already active. It saves and restores outer buffer state across parser calls. And it rejects data callbacks whose spans fall outside the current buffer.
So this is native memory unsafety and parser re-entrancy inside the runtime. It is not a JavaScript logic error or an outdated dependency. Plain node:http servers don’t run this path and are not affected.
Root Cause: CVE-2026-123863 (HTTP/2 unauthenticated crash)
This is a reachable assertion. During teardown, a stream can outlive its session. When the session destructor runs, it checks that its tracked memory counter is back to zero.
An attacker can leave a stream in the right state when the session tears down. The check fails. The process aborts.
The trigger is ordinary: a default HTTP/2 server whose handler sends a response before the full request body arrives. The Node.js project calls this typical server behavior. No special frames or protocol abuse are needed. The crash works over both encrypted and cleartext HTTP/2.
Exploit Path (three steps)
- Entry point. The attacker connects to a Node.js process that terminates TLS or serves HTTP/2 directly. For the memory leak, the target route flushes headers early and echoes or stores request bodies. For the crash, any default HTTP/2 endpoint that replies before the body completes is enough.
- Trigger. For CVE-2026-123864, the attacker shapes request and response timing so an empty TLS write re-enters the parser and exposes a stale buffer span. For CVE-2026-123863, the attacker leaves a stream outstanding, so the session destructor’s memory-counter check fails.
- Impact. The memory bug returns heap contents to the attacker or into storage. That can include TLS private keys and other connections’ request data. The assertion bug aborts the process and drops every in-flight connection on that worker.

The rest of the High-rated set
Four more High-rated bugs hit the server side.
CVE-2026-123866 is a second HTTP/2 memory leak. If a stream is torn down during a backpressured write, freed response-buffer memory can go to the peer. That memory can hold other connections’ responses. From 24.22.0 and 26.9.0 on, a remote peer can trigger it alone. On earlier builds, the server’s own stream teardown keeps it reachable, for example an idle timeout.
CVE-2026-123865 lets a client make a default HTTP/2 server hold memory and file descriptors forever after a protocol error during shutdown. It’s a slow resource drain. You’ll see it as a growing number of CLOSE_WAIT sockets.
CVE-2026-123874 is a use-after-free. It happens when a file-serving stream created with respondWithFile() or respondWithFD() is reset while a write is pending. The advisory describes a virtual call through a freed object. It does not claim code execution was shown.
CVE-2026-126051 crashes a TLS server that uses the SNICallback, OCSPRequest, newSession or resumeSession hooks, or server.addContext().
One more High-rated bug is about authentication. Closing inbound HTTP/2 exposure won’t fix it. CVE-2026-123872 lets a client authenticated for one hostname switch servername during TLS 1.2 renegotiation. The client then carries that authentication into a hostname with stricter client-certificate rules it never met. That’s an mTLS policy bypass. It affects all three supported lines.
Affected Versions
| Package | Vulnerable Versions | Fixed Version | Notes |
|---|---|---|---|
| Node.js 26.x | 26.x before 26.13.1 | 26.13.1 | Both headline bugs apply. Current release line |
| Node.js 24.x | 24.x before 24.22.3 | 24.22.3 | Both headline bugs apply (LTS) |
| Node.js 22.x | 22.x before 22.23.5 | 22.23.5 | CVE-2026-123864 applies. The advisory scopes CVE-2026-123863 to 24.x and 26.x. See note |
| Node.js 20.x, 25.x and other EOL lines | All | No fix | End-of-life. Node.js says EOL versions are always affected. Move to a supported line |
Note on 22.x. The 22.23.5 changelog backports fixes for several HTTP/2 issues. Their advisory entries only name 24.x and 26.x. A backported fix does not prove 22.x was exploitable. Use the advisory’s line scoping for your records. Treat the backports as defense in depth.
One documentation detail. The umbrella advisory lists CVE-2026-106071 as a Low permission-model item. The three release-note pages call that same Low fix CVE-2026-123873. Keep both IDs in your intel records. Don’t try to reconcile the count by hand.
Exposure Analysis
| Environment | Risk Level | Reason |
|---|---|---|
| Internet-exposed Node HTTP/2 or HTTPS services | Critical | Direct unauthenticated reach to the crash and memory leak paths |
| Multi-tenant API processes handling secrets | Critical | CVE-2026-123864 can cross connection boundaries and expose TLS keys and other users’ requests |
| CI/CD workers and build runtimes | High | Often run current Node.js and handle credentials. Outbound and job paths also get fixes in this release |
| Cloud workloads behind TLS passthrough or HTTP/2 load balancers | High | TLS termination at the edge doesn’t help if Node still speaks the native protocol |
| Internal-only Node listeners | Medium | Any user, service or compromised peer on the internal path can reach them. Internal is not a patch exemption |
| Developer environments | Medium | Secrets and tokens live here. Usually less direct exposure, but still part of the fleet update |
A reverse proxy alone doesn’t settle the question. What matters is the protocol that actually reaches the Node.js process.
Say the edge terminates HTTP/2 and the backend only speaks HTTP/1.1. Then the native HTTP/2 paths may be absent on that route. But alternate ports, internal callers, and the TLS and outbound-client CVEs still need their own check.
In your vulnerability records, keep four states separate: component present, affected version, reachable vulnerable path, demonstrated exploitation.
Node.js runs a huge share of server-side JavaScript, so the installed base is large. Nobody has published how many internet-facing instances meet each CVE’s conditions. Use population size as context for prioritization, not as an exploitability number.
Real-World Impact
For CVE-2026-123864, the realistic worst case is cross-tenant secret theft. An attacker hits a vulnerable echo or body-storing route on a shared HTTPS process again and again. They collect heap fragments until private key material or another user’s request shows up.
Leaked TLS private keys allow interception or impersonation later. That risk stays after the patch. This is why key rotation is a separate decision from patching.
CVE-2026-123863 turns into cheap, repeatable denial of service. One request crashes a worker. Script that request and you get a crash loop. A default HTTP/2 service stays down for as long as the traffic keeps coming. No authentication, no unusual payload.
CVE-2026-123865 is the slower version. File descriptors and memory never get released. The host degrades over hours, not seconds.
The advisory reports no attacks using these bugs and lists no public proof of concept. Upstream regression tests for the two memory leak bugs are public in the patch commits. That gives technical reproduction evidence. It does not mean a weaponized exploit or activity in the wild. “No reported PoC” describes current public evidence. It is not a guarantee.
Detection Guidance
Log and telemetry indicators
No single signal clearly fingerprints exploitation. Correlate several signals against connection activity.
For the crash and resource-drain bugs, watch for:
- abrupt process aborts and internal assertion messages in worker logs
- worker restarts you can’t explain
- steady growth in resident memory
- growing file-descriptor counts
- more and more sockets stuck in
CLOSE_WAIT
For the memory leak bugs, there is no clean runtime signal. Focus on inventory and reachability instead. Review every route that echoes or stores request bodies on an HTTPS server that flushes headers early.
For each workload, capture the executable it actually runs, the container image digest and the running process version. A green build or an updated developer shell doesn’t prove the fix. The deployed binary does.
Scanner references
Phoenix Security software composition analysis finds Node.js runtime versions across repositories and running workloads. It flags anything below the fixed release for each line. Pair it with external attack surface management to find internet-facing services still on vulnerable versions.
GitHub dependency scanning and SBOM analysis catch declared runtime versions and base images. Combine them with runtime inventory. That way you see the version that’s actually running, not only the declared one.
Verification steps for teams
- List every workload that runs Node.js. Record the executable path, image digest and running
process.version. - Find which of those processes terminate TLS or serve HTTP/2 to untrusted clients. Find which ones expose early-header-flushing HTTPS handlers or
respondWithFile()/respondWithFD()routes. - Run software composition analysis across all repositories and container images. Look for versions below 22.23.5, 24.22.3 or 26.13.1.
- Check your external attack surface for internet-facing endpoints on vulnerable versions.
- Review per-hostname mTLS configs for the TLS renegotiation and SNI-context authorization bugs.
Remediation Guidance

[IMAGE 3: Versions, detection signals and fix steps. Prompt in section ⑪, Image 3. Alt text below.]
Immediate actions
- Upgrade reachable native HTTP/2, HTTPS and TLS services to the fixed release for their line: 22.23.5, 24.22.3 or 26.13.1.
- Rebuild affected container images on the fixed runtime. Roll out the new images, so the running process is on the patched version, not just the manifest.
- Restart or redeploy the processes. Check that the deployed binary reports a fixed version.
- Finish the fleet update beyond the headline inbound paths. Outbound HTTPS clients, CI workers and embedded runtimes also get fixes in this release.
- Move end-of-life lines like 20.x and 25.x to a supported runtime. No November patch for your branch is not a clean result.
- If an HTTPS server matched the CVE-2026-123864 handler pattern, open a separate assessment. Decide if TLS private keys, in-process credentials, session material, and stored request bodies or logs should be rotated or reissued. Patching does not remove data that may have already leaked.
Temporary mitigations if patching is delayed
The advisory gives no workaround. Treat any interim change as unvalidated risk reduction. Test it for your deployment and remove it after you patch.
Possible measures: restrict direct listener access, isolate affected services, remove native HTTP/2 exposure you don’t need, and check if early-flushing handler patterns can be paused safely.
Don’t assume a WAF, an aggressive restart policy or a lower session limit fixes a memory safety bug. The advisory notes that maxSessionMemory accounting misses the inbound queue involved in one of the HTTP/2 exhaustion bugs. So that control is not a reliable backstop here.
Phoenix Security Recommendations
A sixteen-CVE runtime release can easily turn into a fleet-wide guess. Phoenix Security turns it into a remediation effort with owners and tracking.
Contextual deduplication merges duplicate Node.js findings from software composition analysis, container scanning and attack surface tools into one prioritized backlog. A team sees one Node.js upgrade task per workload. Not the same CVE from five scanners.
Reachability analysis separates processes that actually terminate TLS or serve HTTP/2 from ones that only ship the runtime. This release needs exactly that filter, because each CVE only fires under certain conditions.
Attack surface management finds internet-exposed services still on vulnerable versions and moves them to the top of the queue.
Vulnerability ownership attribution maps each finding to the team that owns the workload. The upgrade lands with the people who can ship it.
Remediation campaigns hold the whole effort together. You create the campaign, assign owners and track fixes. Then you verify that the runtime in production is past the fixed release, and that previously exposed services were reassessed for key rotation.
Ready-made Phoenix campaign
We packed this release into a Phoenix campaign. Import the JSON and Phoenix filters your findings for you.
The campaign picks up the Node.js runtime on the 22.x, 24.x and 26.x lines from your SCA scanners. It keeps High severity findings only. It also matches the CWEs behind this release: 416, 125, 617, 476, 287 and 400.
It comes with two write-ups. A short executive brief for leadership. A technical report for your security engineers.
Import it, assign owners, and track every workload until it runs 22.23.5, 24.22.3 or 26.13.1.
External References
- Node.js Security Releases, November 11, 2026
- Node.js 22.23.5 release notes
- Node.js 24.22.3 release notes
- Node.js 26.13.1 release notes
- CVE-2026-123864 record (cve.org)
- CVE-2026-123863 record (cve.org)
- Upstream HTTPS memory-disclosure patch
- Upstream HTTP/2 memory-disclosure patch
- The Hacker News coverage, November 12, 2026
















