You have reached the beginning of time!

Node.js January 2026 Security Release: What Changed and Why It Matters

Node.js January 2026 Security Release

What Changed and Why It Matters

The Node.js project has released a coordinated security update affecting all active release lines: 25.x, 24.x, 22.x, and 20.x.

This release addresses multiple vulnerabilities across the Node.js runtime, including high-, medium-, and low-severity issues. The fixes span core areas such as memory handling, permission enforcement, protocol processing, TLS error paths, and resource management.

While no new features are introduced, this update is critical for teams running Node.js in production—particularly in network-facing or high-concurrency environments.


What Changed Technically

Vulnerability Details


1. Core Behavior & Memory Safety

Buffer initialization

CVE-2025-55131 (High)

Why this is a security issue

This vulnerability was caused by a race condition in Node.js buffer allocation under specific timing scenarios. Performance optimizations reduced or deferred memory zero-initialization, which—under interruption (such as vm with the timeout option) or concurrent execution—could allow a buffer to become observable before its memory was fully initialized.

When this occurred, buffers created via Buffer.alloc() or TypedArray constructors could contain residual data from previous allocations, breaking the expectation of zero-filled memory and potentially exposing in-process secrets.

What changed

Node.js now enforces strict memory initialization before exposing buffers to userland. Allocation and exposure are no longer interleaved, eliminating the timing window where partially initialized memory could be observed.

This restores deterministic and safe buffer semantics even under timeouts or concurrency.

How do I know if this affects me?

You may be affected if your application allocates buffers using Buffer.alloc() or TypedArray constructors and exposes their contents—directly or indirectly—through remote interfaces such as HTTP APIs, RPC handlers, or streaming endpoints.

The risk increases in scenarios where:

  • buffer allocation occurs under concurrency or sustained load
  • execution is constrained by timeouts (for example, when using vm with the timeout option)
  • untrusted input can influence execution timing or allocation patterns

If buffer contents are serialized, logged, or returned to clients without additional validation or sanitization, residual memory data could be unintentionally exposed.

Applications that keep buffer usage strictly internal and never surface raw buffer data externally are significantly less likely to be impacted.


2. Permission Model Hardening

Symlink handling

CVE-2025-55130 (High)

Why this is a security issue

This vulnerability stemmed from how Node.js’s Permission Model handled filesystem access when symlinks were involved. While read and write permissions were enforced on direct paths, symlink traversal was not fully constrained, allowing relative symlinks to escape the intended filesystem boundary.

Under these conditions, code running with restricted --allow-fs-read or --allow-fs-write permissions could access files outside the approved directory, violating isolation guarantees and enabling unauthorized file access.

What changed

Node.js now requires explicit read and write permissions when resolving and interacting with symlink-based APIs. This ensures that symlink resolution is subject to the same permission checks as direct filesystem access, closing the path traversal vector.

Why it matters in practice

Applications relying on the Permission Model for isolation—especially in sandboxed, containerized, or multi-tenant environments—are directly impacted. This fix restores the expectation that filesystem boundaries cannot be bypassed via symlinks, reinforcing secure-by-default behavior in restricted execution contexts.


Permission Model network bypass through Unix Domain Sockets (UDS)

CVE-2026-21636 (Medium)

Why this is a security issue

This vulnerability was caused by a gap in how Node.js’s Permission Model enforced network restrictions for Unix Domain Socket (UDS) connections. While IP-based networking was correctly gated behind --allow-net, UDS connections were not consistently subjected to the same checks.

As a result, applications running with restricted network permissions could still establish connections to local sockets through APIs such as net, tls, or fetch, bypassing the intended isolation boundary and allowing access to privileged local services.

What changed

Node.js now applies network permission checks to Unix Domain Socket connections. UDS-based communication is treated consistently with other network operations, ensuring that socket access is explicitly governed by declared network permissions.


Timestamp updates

CVE-2025-55132 (Low)

Why this is a security issue

This issue arose from an inconsistency in how the Permission Model enforced filesystem restrictions. While write permissions were correctly required for most file-modifying operations, fs.futimes() allowed file access and modification timestamps to be updated even when the process had read-only permissions.

Although this did not enable direct data modification, it allowed observable state changes that conflicted with declared access restrictions and could be used to obscure file access patterns or weaken the reliability of audit logs.

What changed

When the Permission Model is enabled, fs.futimes() is now fully disabled. This aligns timestamp updates with existing write-permission requirements and removes the discrepancy between futimes() and other filesystem mutation APIs.


3. HTTP & Protocol Handling

HTTP/2 HEADERS frame handling

CVE-2025-59465 (High)

Why this is a security issue

This vulnerability was caused by how Node.js handled malformed HTTP/2 HEADERS frames containing invalid or oversized HPACK data. In applications where no explicit error handler was attached to the underlying TLSSocket, a low-level socket error raised during TLS connection initialization could go unhandled, causing the entire process to crash instead of gracefully closing the affected connection.

This meant a single malformed request could trigger a remote denial-of-service condition, particularly in HTTP/2 servers relying on default TLS socket behavior.

What changed

Node.js now installs a default error handler at the TLSSocket level. Protocol-level errors triggered during HTTP/2 connection setup are safely contained, ensuring the connection is terminated without crashing the process.

Defensive configuration (recommended)

Before this fix, servers that explicitly handled TLS socket errors were less likely to be impacted. While the security release adds a default handler, attaching explicit error handlers remains a good defensive practice:

const server = http2.createSecureServer({ /* TLS options */ });
server.on('secureConnection', (socket) => {
  socket.on('error', (err) => {
    console.error(err);
  });
});

Why it matters in practice

HTTP/2 servers are commonly exposed to untrusted traffic. This fix significantly improves resilience by ensuring that malformed or malicious protocol input cannot crash the entire process, reducing the blast radius to a single connection instead of the whole server.


4. Error Handling & Crash Resilience

async_hooks stack overflow handling

CVE-2025-59466 (Medium) Reproduction details: Reproduction details here

Why this is a security issue

This vulnerability was caused by incorrect error propagation when async_hooks.createHook() was enabled. Under specific conditions involving deep or recursive async execution, a Maximum call stack size exceeded error could bypass normal Node.js error-handling paths and terminate the process directly.

Because the error never reached standard handlers such as process.on('uncaughtException'), applications were unable to recover or fail gracefully, making the crash effectively unrecoverable and enabling denial-of-service scenarios.

What changed

Node.js modified how stack overflow exceptions originating from async_hooks are propagated. These exceptions are now routed through the regular error-handling paths instead of terminating the process immediately.

This aligns stack overflow behavior under async_hooks with the broader runtime error propagation model.

Why it matters in practice

Applications that rely on async_hooks or AsyncLocalStorage for observability, tracing, or instrumentation are directly affected. This fix prevents unexpected process termination and significantly improves stability under error conditions in production.


5. Resource Exhaustion & TLS

TLS certificate parsing

CVE-2025-59464 (Medium)

Why this is a security issue

This vulnerability was caused by a memory leak in Node.js’s TLS certificate parsing logic. When processing client certificates, certain X.509 fields were converted to UTF-8 without properly releasing allocated memory.

A remote client could exploit this behavior only in applications that explicitly iterate over client certificate fields—for example, by calling socket.getPeerCertificate(true). In those cases, repeatedly establishing TLS connections with client certificates could cause steady and unbounded memory growth over time.

While not immediately obvious, this pattern could eventually lead to resource exhaustion and denial-of-service conditions.

What changed

Node.js now ensures that all buffers allocated during TLS certificate parsing are correctly freed, including failure paths. This closes the leak and guarantees proper resource cleanup when handling client certificates.


TLS PSK / ALPN callback handling

CVE-2026-21637 (Medium)

Why this is a security issue

This vulnerability stemmed from how Node.js handled synchronous exceptions thrown inside TLS PSK and ALPN callbacks. When these callbacks processed attacker-controlled input during the TLS handshake, thrown exceptions could bypass standard TLS error-handling paths.

As a result, errors could either crash the process immediately or leave file descriptors unreleased, enabling denial-of-service conditions through repeated connection attempts.

What changed

Node.js now consistently routes exceptions raised in PSK and ALPN callbacks through the appropriate TLS error handlers. This ensures that failures are visible, connections are properly terminated, and resources are reliably cleaned up.

Why it matters in practice

TLS servers using PSK or ALPN callbacks are often long-running and exposed to untrusted clients. Proper error propagation prevents silent resource leaks and unexpected crashes, significantly improving resilience and reliability.


Recommendations & Actions

1. Upgrade Node.js promptly

Confirm the Node.js version currently running in your environments:

node -v

Upgrade to the latest patched release within your active major version (20.x, 22.x, 24.x, or 25.x).

Example using nvm:

nvm install 22  
nvm use 22  

Being on the correct major version is not sufficient.
The vulnerabilities addressed in this release are fixed only in patch versions.


2. Verify whether you are affected

If you are unsure whether your current Node.js version is impacted by this security release, use the official community tool:

is-my-node-vulnerable
https://github.com/nodejs/is-my-node-vulnerable

The tool evaluates your Node.js version against known CVEs and helps determine whether an upgrade is required.


3. Validate buffer-heavy code paths under load

Applications that frequently allocate buffers—such as those handling streaming, parsing, compression, or cryptography—should be validated under realistic concurrency.

Example stress test:

npx autocannon -c 100 -d 30 http://localhost:3000

During testing, closely monitor:

  • overall memory usage and trends
  • garbage collection frequency and pause time
  • stability under sustained concurrency

Several fixes in this release address timing- and concurrency-sensitive behavior that may not surface in unit or integration tests.


4. Re-evaluate Permission Model configurations

For applications running with the Permission Model enabled:

node --permission --allow-fs-read=/app/data

Review configurations with particular attention to:

  • symlink usage in filesystem paths
  • Unix Domain Socket communication
  • network access assumptions tied to --allow-net

Some configurations that previously appeared to work may now fail correctly, exposing overly permissive or incomplete security assumptions.


5. Strengthen HTTP/2 error handling

If your application exposes HTTP/2 endpoints, ensure protocol-level errors cannot escalate into process-level failures.

Example pattern:

server.on('stream', (stream) => {
  try {
    // application logic
  } catch (err) {
    stream.close();
  }
});

While this release improves default handling, explicit error boundaries further reduce the impact of malformed or unexpected input in production.


6. Improve observability around error paths

Several vulnerabilities fixed in this release occur outside the “happy path.” To detect similar issues early, add monitoring around:

  • long-term memory growth (not only short-lived spikes)
  • TLS handshake and callback errors
  • open socket and file descriptor counts
  • unexpected process restarts

Gradual resource exhaustion and silent failures are often early indicators of deeper issues.


Additional Resources

For authoritative details, CVE references, and tools related to this security release, consult the following resources:


Closing Perspective

This security release reinforces a recurring reality in production systems:

Most failures do not start with explicit errors.
They start with memory pressure, subtle permission gaps, and fragile edge cases.

By addressing these vulnerabilities, Node.js becomes more predictable, more resilient, and safer to operate at scale—particularly under real-world conditions.

Thank you for keeping your runtimes up to date.
Happy coding, and stay safe.

The NodeSource platform offers a high-definition view of the performance, security and behavior of Node.js applications and functions.

Start for Free