HexBrain

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:

  1. 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.
  2. 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").
  3. In another terminal, run the example client: /tmp/curl/docs/examples/websocket ws://127.0.0.1:9000/.
  4. 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

This report was disclosed publicly on HackerOne and belongs to its author and the program. See the original