CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-9MQV-5HH9-4CGG

GHSA-9MQV-5HH9-4CGG: Unauthenticated Memory-Leak Denial of Service in @hono/node-server WebSocket Handshake Parser

Alon Barad
Alon Barad
Software Engineer

Jul 22, 2026·6 min read·3 visits

Executive Summary (TL;DR)

Unauthenticated memory leak in @hono/node-server allows remote attackers to cause process termination via aborted WebSocket handshakes.

An unauthenticated memory-leak Denial of Service (DoS) vulnerability exists in the Node.js Adapter for Hono (@hono/node-server) during the WebSocket handshake upgrade process. If a client initiates a WebSocket upgrade but the process is aborted or fails, resources are permanently retained in memory, leading to heap exhaustion.

Vulnerability Overview

The Hono Node.js adapter, @hono/node-server, facilitates hosting Hono applications within a Node.js runtime environment. A key component of this adapter is its WebSocket support, which handles the handshaking and upgrading of HTTP connections to WebSocket connections. This implementation exposes a public attack surface through any route configured to upgrade connections via the upgradeWebSocket utility.

The vulnerability identified under GHSA-9MQV-5HH9-4CGG is a memory leak occurring during the WebSocket handshake process. If a client initiates a handshake that subsequently fails or is aborted before completion, the server fails to clean up internal state structures. This results in uncontrolled resource consumption (CWE-400), potentially leading to process termination due to heap exhaustion.

An unauthenticated remote attacker can exploit this condition by sending a flood of invalid or aborted WebSocket upgrade requests. Each failed handshake permanently leaks the associated request objects, pending Promise contexts, and network socket descriptors. Over time, this cumulative resource leak exhausts the available V8 heap memory, resulting in a Denial of Service (DoS).

Root Cause Analysis

The root cause of GHSA-9MQV-5HH9-4CGG lies in how the @hono/node-server adapter tracks and processes pending WebSocket handshakes. The application utilizes a module-level Map named waiterMap to associate incoming HTTP upgrade requests with their corresponding pending Promise resolution callbacks. The keys in this Map are the strong references to the request's IncomingMessage objects.

When an upgrade request is received, the adapter initializes a new Promise using the waitForWebSocket function and inserts the request and its resolve callback into waiterMap. Under a successful handshake scenario, the underlying WebSocket server (utilizing the ws library) completes the connection and fires a connection event. The event handler retrieves the corresponding entry from waiterMap, invokes resolve, and deletes the key-value pair to free the resources.

If the handshake is aborted, such as when a client provides an invalid Sec-WebSocket-Key or drops the connection abruptly, the connection event is never triggered. Because the vulnerable implementation does not register any listeners for failed or aborted connections, the entry is never removed from waiterMap. Consequently, the Promise remains permanently in a pending state, and the strongly-referenced IncomingMessage and associated V8 lexical scopes are shielded from garbage collection.

Code Analysis

To understand the precise code-level flaw, we examine the vulnerable design in src/websocket.ts. In the original implementation, the waiterMap only tracked the success resolver:

const waiterMap = new Map<
  IncomingMessage,
  { resolve: (ws: WebSocketLike) => void; connectionSymbol: symbol }
>()

The corresponding helper function registered the pending state without any mechanism to handle errors or abort signals:

const waitForWebSocket: WaitForWebSocket = (request, connectionSymbol) => {
  return new Promise<WebSocketLike>((resolve) => {
    waiterMap.set(request, { resolve, connectionSymbol })
  })
}

The patch implemented in commit 3a21938c418340e980cb7ffa88e78369f78392d1 corrects this by introducing active rejection capabilities and tying the promise lifetime to the physical socket's close event.

First, the waiterMap is modified to include a reject handler:

const waiterMap = new Map<
  IncomingMessage,
  {
    resolve: (ws: WebSocketLike) => void
    reject: (reason: Error) => void
    connectionSymbol: symbol
  }
>()

Second, a reclamation routine rejectWaiter is introduced to safely delete and reject the outstanding waiter:

const rejectWaiter = (request: IncomingMessage) => {
  const waiter = waiterMap.get(request)
  if (waiter) {
    waiterMap.delete(request)
    waiter.reject(new Error('WebSocket handshake aborted'))
  }
}

Third, the socket lifecycle is actively monitored during the upgrade process. A listener is attached to the socket's close event to ensure cleanup happens if the handshake fails:

const reclaimWaiterOnClose = () => rejectWaiter(request)
socket.once('close', reclaimWaiterOnClose)
 
wss.on('headers', addResponseHeaders)
try {
  wss.handleUpgrade(request, socket, head, (ws) => {
    socket.off('close', reclaimWaiterOnClose)
    wss.emit('connection', ws, request)
  })
} finally {
  // Ensure synchronous exceptions do not bypass standard execution flow
}

Exploitation Methodology

Exploitation of this memory-leak vulnerability requires no authentication and can be executed via a low-bandwidth, unauthenticated attack path. The attacker targets any endpoint on the Hono server configured to support WebSocket upgrades.

The attack begins by establishing a standard TCP connection to the target port. Once connected, the attacker transmits a malformed HTTP GET request mimicking a WebSocket upgrade. By omitting or corrupting a mandatory header, such as sending Sec-WebSocket-Key: not-a-valid-key, the attacker forces the underlying ws engine to terminate the upgrade process and respond with an HTTP 400 Bad Request status code.

Following the receipt of the error response, or immediately after transmitting the payload, the attacker closes the TCP connection. On vulnerable servers, this pattern leaves a dangling entry in the waiterMap and a pending Promise in memory. Because each aborted request leaks a block of heap memory, automating this request sequence leads directly to an Out of Memory (OOM) crash.

Impact Assessment

The security impact of GHSA-9MQV-5HH9-4CGG is a complete loss of availability for the affected Hono server. Because the memory leak is triggered prior to authentication, any remote user can perform the exploitation steps, making the complexity low.

The leaked resources include not only the small waiterMap entry but also the entire context of the IncomingMessage object, which contains request headers, socket references, and associated buffer allocations. As these objects accumulate in the V8 heap, garbage collection cycles become increasingly frequent and CPU-intensive, degrading server performance before ultimate termination.

When heap limits are exceeded, the Node.js runtime throws an unhandled Out of Memory error and exits. In environments lacking automated process supervisors or container orchestrators, this results in persistent downtime. Even with automatic restarts, continuous execution of the attack pattern can prevent legitimate users from establishing reliable connections.

Remediation and Detection

The primary remediation strategy is upgrading the @hono/node-server package to version 2.0.10 or later. This release incorporates the socket-lifetime listener that guarantees cleanup on connection closure.

npm install @hono/node-server@2.0.10

For environments where upgrading is not immediately possible, deploying a reverse proxy such as Nginx or HAProxy in front of the Node.js application can mitigate the issue. The reverse proxy should be configured to validate incoming WebSocket headers strictly, blocking or rejecting malformed handshake requests before they reach the Node.js adapter.

Detection of active exploitation can be achieved by monitoring V8 heap metrics and tracking socket state transitions. A steady, linear rise in resident set size (RSS) or heap usage coupled with a high count of aborted TCP connections or HTTP 400 responses on upgrade routes suggests exploitation or persistent configuration issues.

Technical Appendix

CVSS Score
7.5/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

Affected Systems

@hono/node-server
AttributeDetail
CWE IDCWE-400, CWE-401, CWE-772
Attack VectorNetwork (AV:N)
CVSS v3.17.5 (High)
Exploit StatusProof of Concept available
ImpactDenial of Service (DoS) via Heap Exhaustion
Fixed Version>= 2.0.10
CWE-400
Uncontrolled Resource Consumption

Vulnerability Timeline

Security patch authored and committed to the repository by Yusuke Wada
2026-07-15
Version v2.0.10 of @hono/node-server published to the npm registry
2026-07-15
Security advisory GHSA-9MQV-5HH9-4CGG publicly published
2026-07-15

References & Sources

  • [1]GHSA-9mqv-5hh9-4cgg Security Advisory
  • [2]Release v2.0.10

More Reports

•about 1 hour ago•GHSA-HRXH-6V49-42GF
8.6

GHSA-HRXH-6V49-42GF: HTTP/2 Control Buffer Flooding and xDS RBAC Parsing Weaknesses in gRPC-Go

GHSA-HRXH-6V49-42GF is a critical security advisory addressing two distinct vulnerabilities within gRPC-Go: an HTTP/2 Control Buffer Flooding weakness that allows unauthenticated denial of service, and xDS Role-Based Access Control parser weaknesses that lead to authorization bypasses and application panics.

Alon Barad
Alon Barad
2 views•8 min read
•about 3 hours ago•GHSA-CJ75-F6XR-R4G7
5.1

GHSA-cj75-f6xr-r4g7: Cross-Site Scripting (XSS) Bypass via SVG href Attributes in rails-html-sanitizer

An issue in rails-html-sanitizer allowed attackers to bypass restrictions on SVG reference elements (such as <use> or <feImage>) when specific custom configurations allowed these tags. Because the sanitizer only restricted the legacy 'xlink:href' attribute to local references, modern browsers supporting plain 'href' attributes according to the SVG 2 specification would load external resources. This could lead to Cross-Site Scripting (XSS) or user tracking.

Alon Barad
Alon Barad
1 views•6 min read
•about 4 hours ago•GHSA-RWJ8-PGH3-R573
10.0

GHSA-RWJ8-PGH3-R573: Environment Variable Exfiltration and Protocol Validation Bypass in GitPython

An input validation flaw in GitPython allows remote attackers to exfiltrate system environment variables and bypass safe-protocol restrictions via crafted repository URLs passed to the clone API.

Alon Barad
Alon Barad
2 views•7 min read
•about 5 hours ago•GHSA-8R6M-32JQ-JX6Q
8.7

GHSA-8R6M-32JQ-JX6Q: XML Entity Expansion Bypass in fast-xml-parser via Repeated DOCTYPE Declarations

A Denial of Service (DoS) vulnerability has been identified in the Node.js XML parsing library fast-xml-parser. The flaw allows unauthenticated remote attackers to cause severe CPU exhaustion, event-loop blocking, and system crashes by sending a crafted XML payload containing repeated DOCTYPE declarations that bypass recursive entity expansion protections.

Amit Schendel
Amit Schendel
3 views•8 min read
•about 6 hours ago•GHSA-F88M-G3JW-G9CJ
8.5

GHSA-F88M-G3JW-G9CJ: Multiple Memory Safety and Integer Overflow Vulnerabilities in libvips affecting sharp

The high-performance Node.js image processing library sharp inherits several high and medium-severity security vulnerabilities from its underlying native dependency libvips. These include integer overflows in dimensions calculation, heap-based buffer overflows in GIF/TIFF and JPEG2000 processing, and out-of-bounds reads in the EXIF directory decoder, enabling denial of service and potential code execution.

Amit Schendel
Amit Schendel
5 views•7 min read
•about 7 hours ago•CVE-2026-16221
7.5

CVE-2026-16221: Interpretation Conflict leading to Host Confusion and SSRF Bypass in fast-uri

An interpretation conflict (CWE-436) exists in fast-uri due to differing handling of backslash characters between RFC 3986 and the WHATWG URL specification. This differential allows remote attackers to bypass SSRF filters and origin-allowlist protections when fast-uri is used in conjunction with WHATWG-compliant HTTP clients like Node.js native fetch or undici.

Amit Schendel
Amit Schendel
5 views•8 min read