curl · Report #3474865
libcurl WebSocket handshake accepts any Sec-WebSocket-Accept
N/Astatus
10upvotes
23 Dec 2025disclosed
How it was found
Summary: libcurl upgrades to WebSocket without validating Sec-WebSocket-Accept, allowing a spoofed 101 response to complete the handshake and inject frames; AI assistance was used to draft this report.
Steps to Reproduce:
- Clone and build curl from source: git clone --depth=1 https://github.com/curl/curl /tmp/curl && cd /tmp/curl && autoreconf -fi && ./configure --disable-shared --without-ssl --without-libpsl --disable-dependency-tracking && make -j4 && make -C docs/examples websocket.
- Run a TCP server that replies with a fixed wrong Sec-WebSocket-Accept value and a text frame, without reading the request (example: HTTP/1.1 101 Switching Protocols + Upgrade: websocket + Connection: Upgrade + Sec-WebSocket-Accept: WRONGKEY + a single WS text frame "hello").
- In another terminal, run the example client: /tmp/curl/docs/examples/websocket ws://127.0.0.1:9000/.
- Observe output like "ws: received TEXT frame 'hello'" even though the server used Sec-WebSocket-Accept: WRONGKEY; the client should have rejected the handshake but accepts it.
Impact: Handshake integrity is broken: a spoofed or malicious intermediary can complete the WebSocket upgrade without knowing the client’s nonce, enabling protocol confusion or data injection for libcurl-based WebSocket clients. This violates RFC 6455’s challenge-response protection and allows blind 101 responses to be accepted.
Impact
Look at original report impact