Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-62389

CVE-2026-62389: ws Library Memory Exhaustion Vulnerability

CVE-2026-62389 is a memory exhaustion flaw in ws library before 8.21.1 that enables denial of service attacks through incomplete WebSocket fragments. This article covers technical details, affected versions, and mitigation.

Published:

CVE-2026-62389 Overview

CVE-2026-62389 is a memory exhaustion vulnerability in the ws WebSocket library for Node.js, affecting versions prior to 8.21.1. The flaw resides in lib/receiver.js, where the fragment guard only triggers when the fragment count reaches maxFragments. Attackers can send a text frame with FIN=0 followed by continuation frames without ever completing the sequence. Each incomplete fragment is retained as a separate Buffer object with significant overhead, exhausting heap memory. The vulnerability is classified under [CWE-770] (Allocation of Resources Without Limits or Throttling) and enables unauthenticated denial of service against any Node.js service using the affected library.

Critical Impact

Unauthenticated remote attackers can trigger heap exhaustion and crash Node.js WebSocket servers by sending incomplete fragmented messages, resulting in denial of service.

Affected Products

  • ws (websockets/ws) versions before 8.21.1
  • Node.js applications and servers embedding vulnerable ws versions
  • Downstream libraries and frameworks bundling ws as a transitive dependency

Discovery Timeline

  • 2026-07-15 - CVE-2026-62389 published to NVD
  • 2026-07-15 - Last updated in NVD database

Technical Details for CVE-2026-62389

Vulnerability Analysis

The ws library implements the WebSocket protocol, which supports message fragmentation using the FIN bit and continuation frames. When FIN=0, the receiver stores the payload fragment and waits for subsequent continuation frames until a frame with FIN=1 arrives.

In versions before 8.21.1, the receiver enforced the maxFragments limit only when the accumulated fragment count reached the configured maximum. The default value of maxFragments was 131072, and maxBufferedChunks defaulted to 1048576. Both defaults were high enough that a single malicious peer could allocate massive amounts of memory before triggering any protective threshold. Each retained Buffer object carries per-object overhead in the V8 heap, amplifying the impact well beyond the raw payload size.

Root Cause

The root cause is insufficient resource throttling on incomplete fragmented WebSocket messages. The library retains all received fragments in memory pending completion of the message. Because the default upper bounds were permissive, an attacker could stream large numbers of small continuation frames without ever setting FIN=1, forcing the server to hold every fragment indefinitely.

Attack Vector

An unauthenticated attacker opens a WebSocket connection to a vulnerable server and sends a text frame with FIN=0. The attacker then streams continuation frames indefinitely, never sending a frame with FIN=1. The server buffers each fragment as a distinct Buffer instance, consuming heap memory until the Node.js process crashes with an out-of-memory condition.

javascript
// Security patch in lib/websocket-server.js and lib/websocket.js
// [fix] Lower default values of `maxBufferedChunks` and `maxFragments`

- * @param {Number} [options.maxBufferedChunks=1048576] The maximum number of
+ * @param {Number} [options.maxBufferedChunks=262144] The maximum number of
  *     buffered data chunks
- * @param {Number} [options.maxFragments=131072] The maximum number of message
+ * @param {Number} [options.maxFragments=16384] The maximum number of message
  *     fragments
  * @param {Number} [options.maxPayload=104857600] The maximum allowed message
  *     size

// Source: https://github.com/websockets/ws/commit/f197ac65140920bdcecdab74bfc69c2d7858e55d

The patch reduces maxBufferedChunks from 1048576 to 262144 and maxFragments from 131072 to 16384, shrinking the pre-completion memory ceiling by an order of magnitude.

Detection Methods for CVE-2026-62389

Indicators of Compromise

  • WebSocket connections that open a message with FIN=0 and stream continuation frames without ever terminating with FIN=1.
  • Sustained growth of Node.js process resident set size (RSS) and V8 heap size correlated with active WebSocket sessions.
  • Repeated FATAL ERROR: JavaScript heap out of memory crashes in Node.js services exposing ws endpoints.

Detection Strategies

  • Inspect WebSocket frame telemetry for connections producing an abnormally high count of continuation frames from a single peer.
  • Monitor per-connection buffered fragment counts and alert when a session exceeds a defined ceiling (e.g., several hundred queued fragments).
  • Correlate reverse-proxy or load-balancer logs with backend memory spikes to identify offending source IPs.

Monitoring Recommendations

  • Instrument Node.js services with heap and event-loop metrics via process.memoryUsage() and export to Prometheus or an equivalent collector.
  • Enable rate limiting and per-IP connection caps on the WebSocket termination layer.
  • Log the ws server option values (maxFragments, maxBufferedChunks, maxPayload) at process startup for audit and drift detection.

How to Mitigate CVE-2026-62389

Immediate Actions Required

  • Upgrade the ws package to version 8.21.1 or later in all direct and transitive dependencies.
  • Audit package-lock.json and yarn.lock files for pinned vulnerable versions and refresh the dependency tree.
  • Restart affected Node.js services after upgrading to ensure the patched module is loaded.

Patch Information

The fix is delivered in ws 8.21.1 via commit f197ac6. The patch lowers the default maxFragments to 16384 and maxBufferedChunks to 262144. See the VulnCheck Security Advisory and the GitHub Issue Discussion for additional context.

Workarounds

  • Explicitly set stricter values for maxFragments, maxBufferedChunks, and maxPayload when instantiating WebSocket.Server or WebSocket clients until the upgrade can be applied.
  • Terminate WebSocket connections that remain in an incomplete fragmented state beyond a short timeout enforced at the application layer.
  • Front the service with a reverse proxy that enforces connection limits, request rate limits, and idle timeouts on WebSocket streams.
bash
# Configuration example: enforce conservative limits when creating the server
node -e "
const { WebSocketServer } = require('ws');
const wss = new WebSocketServer({
  port: 8080,
  maxPayload: 1 * 1024 * 1024,   // 1 MiB
  maxFragments: 1024,             // hard cap well below patched default
  maxBufferedChunks: 4096         // hard cap on queued chunks
});
wss.on('connection', (ws) => {
  const killer = setTimeout(() => ws.terminate(), 30000);
  ws.on('message', () => clearTimeout(killer));
});
"

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.