CVE-2026-105481

Concurrent Execution using Shared Resource with Improper Synchronization
Affects
Node.js
in
Node.js
No items found.
Versions
<=21.7.3, >=22.0.0 <22.23.4, >=23.0.0 <=23.11.1, >=24.0.0 <24.22.1, >=25.0.0 <=25.9.0, >=26.0.0 <26.12.1

Patch Available.

Exclamation circle icon
Patch Available

This Vulnerability has been fixed in the Never-Ending Support (NES) version offered by HeroDevs.

Overview

Node.js is an asynchronous, event-driven JavaScript runtime designed for building scalable network applications. Its http module's Agent class pools keep-alive connections for outgoing HTTP client requests, handing an idle socket from the pool to the next request for the same host. Socket reads are performed by libuv in Node.js's native code and only reach JavaScript when the event loop polls for I/O.

A time-of-check to time-of-use (TOCTOU) race condition vulnerability (CVE-2026-105481) has been identified in Node.js's http.Agent connection reuse. HTTP/1.1 has no response identifiers, so a client can only trust that the next response on a connection answers the request it just sent. The fix for CVE-2026-48931 added a guard that destroys an idle pooled socket when unsolicited data arrives on it. However, the guard only runs when the event loop polls for I/O. If an unsolicited response has already reached the socket but has not been read when the socket is handed to a new request, for example because the event loop was busy with synchronous work, the guard is removed without seeing it and the data is parsed as the response to the new request.

This behaviour maps to CWE-367 (Time-of-check Time-of-use (TOCTOU) Race Condition), where a product checks the state of a resource before using it, but the state can change between the check and the use. In Node.js, the Agent treats an idle socket as clean because the guard has not fired, while response bytes are already waiting in the operating system's buffer. The client then accepts a response that was written before its request was sent, and every later response on that connection is shifted by one.

Exploitation requires a client that uses an http.Agent with keep-alive, which is the default for the global agent, and a peer that can write to the connection, such as a malicious or compromised upstream server. After completing a legitimate response, the peer writes an extra, well-formed response and relies on it arriving while the client's event loop is blocked, or while the socket is being passed straight to a queued request. Clients that do not reuse connections, or that only talk to trusted upstreams, are not exposed. The Node.js project describes the issue as affecting its supported 22.x, 24.x and 26.x lines. Upstream releases before 22.23.0, 24.17.0 and 26.3.1, and every End-of-Life line, never received the CVE-2026-48931 guard and accept such a response whatever the timing. The 12.x through 20.x lines patched for CVE-2026-48931 by HeroDevs carry an earlier form of the same guard and have the same gap.

Details

Module Info

  • Product: Node.js
  • Affected packages: node (built-in http module; lib/_http_agent.js, src/stream_wrap.cc)
  • Affected versions: <=21.7.3, >=22.0.0 <22.23.4, >=23.0.0 <=23.11.1, >=24.0.0 <24.22.1, >=25.0.0 <=25.9.0, >=26.0.0 <26.12.1
  • GitHub repository: https://github.com/nodejs/node
  • Published packages: https://nodejs.org/en/download
  • Package manager: Not applicable; Node.js is distributed as runtime builds from nodejs.org rather than as a published npm package
  • Fixed in: Node.js 22.23.4, 24.22.1, and 26.12.1; Node.js NES v12.22.21, v14.21.14, v16.20.15, v18.20.20, v20.20.5, v20.20.13, and v22.23.5

Vulnerability Info

This Medium-severity vulnerability is found in the free-socket handling of http.Agent in Node.js's http module (lib/_http_agent.js). The HackerOne CNA scores it 6.5 (CVSS v3.0), and the Node.js project also rates it Medium. NVD has not yet scored it.

When a response completes on a keep-alive socket, the Agent either passes the socket straight to a request waiting in its queue, or puts it in the free pool with the CVE-2026-48931 data guard installed. The guard destroys the socket if a read completes while it is idle. When a later request takes a socket from the pool, the Agent removes the guard and reuses the socket.

The guard can only react to data that libuv has already read, which happens when the event loop polls for I/O. Neither the pool path nor the queued-request path checked whether data was waiting unread in the operating system's socket buffer. If the peer's extra response arrived after the last poll, the socket was handed over with the bytes still pending, the guard was removed, and the new request's HTTP parser read them on the next poll as its own response. The fix adds a native check that peeks at the socket without consuming data, and destroys any kept-alive socket that has data, EOF or an error pending before it is given to a request.

An attacker would need to control or tamper with an upstream that the client reaches over a pooled connection, and to time the extra response so that it lands while the client is busy. Synchronous work in the client, such as parsing a large body, widens that window.

Note: Applications whose pool is shared across users or trust levels are most exposed, because a shifted response can deliver one user's data to another. Disabling keep-alive for untrusted upstreams avoids the reuse, at a performance cost, but does not remove the underlying issue.

Mitigation

Node.js 22.x, 24.x and 26.x are supported and are fixed in 22.23.4, 24.22.1 and 26.12.1 and later. Every other release line is past its support window and never received an upstream fix. Node.js 12.x reached End-of-Life on April 30, 2022; Node.js 14.x on April 30, 2023; Node.js 16.x on September 11, 2023; Node.js 18.x on April 30, 2025; Node.js 19.x on June 1, 2023; Node.js 20.x on April 30, 2026; Node.js 21.x on June 1, 2024; Node.js 23.x on June 1, 2025; and Node.js 25.x on June 1, 2026. For more information see the Node.js previous releases schedule.

Users of the affected components should apply one of the following mitigations:

  • Upgrade to Node.js 22.23.4, 24.22.1 or 26.12.1 or later on those lines, all of which include this fix.
  • Migrate affected applications away from the End-of-Life Node.js release lines.
  • Leverage a commercial support partner like HeroDevs for post-EOL security support, through Node.js NES.

Credits

  • Hasan Flayyih Abdullah (reporter)
  • jasnell (remediation developer)
Vulnerability Details
Severity
Level
CVSS Assessment
Low
>=0 <4
Medium
>=4 <6
High
>=6 <8
Critical
>=8 <10
Medium
ID
CVE-2026-105481
PROJECT Affected
Node.js
Versions Affected
<=21.7.3, >=22.0.0 <22.23.4, >=23.0.0 <=23.11.1, >=24.0.0 <24.22.1, >=25.0.0 <=25.9.0, >=26.0.0 <26.12.1
NES Versions Affected
Published date
November 6, 2026
≈ Fix date
October 21, 2026
Category
Concurrent Execution using Shared Resource with Improper Synchronization
Vex Document
Download VEXHow do I use it?
Sign up for the latest vulnerability alerts fixed in
NES for Node.js
Rss feed icon
Subscribe via RSS
or

By submitting the form I acknowledge receipt of our Privacy Policy.

Thanks for signing up for our Newsletter! We look forward to connecting with you.
Oops! Something went wrong while submitting the form.