Skip to content

connectd: treat websocket handshake headers as case-insensitive - #9308

Merged
daywalker90 merged 1 commit into
ElementsProject:masterfrom
coreyphillips:connectd-ws-case-insensitive-headers
Aug 26, 2026
Merged

connectd: treat websocket handshake headers as case-insensitive#9308
daywalker90 merged 1 commit into
ElementsProject:masterfrom
coreyphillips:connectd-ws-case-insensitive-headers

Conversation

@coreyphillips

Copy link
Copy Markdown
Contributor

Fixes #9307.

The websocket handshake parser matches header names byte-exactly (get_http_hdr) and the Upgrade/Connection values with case-sensitive strstr. Header field names are case-insensitive per RFC 9110 section 5.1, and RFC 6455 says the Upgrade and Connection values are "treated as an ASCII case-insensitive value" (already quoted in the comment above http_respond).

Practical impact: Node.js's built-in WebSocket (undici) lowercases all request headers, so it can never connect to a bind-addr=ws: listener and gets "400 I only speak websocket". Browsers happen to send RFC casing and work.

Changes:

  • get_http_hdr matches header names case-insensitively (strncasecmp, as used elsewhere in the tree)
  • Upgrade/Connection values use a small case-insensitive contains helper
  • Sec-WebSocket-Version stays an exact "13" comparison and the key is base64 data, both unchanged
  • run-websocket.c gains a second handshake with lowercased header names and mixed-case values, as sent by Node; same Sec-WebSocket-Accept expected

Verified the failure mode against a live v26.06.1 bind-addr=ws: listener with raw replays (lowercased names rejected before, accepted with this change per the unit test vector).

@Andezion
Andezion force-pushed the connectd-ws-case-insensitive-headers branch from 880909c to 4438a15 Compare July 16, 2026 08:07
Andezion
Andezion previously approved these changes Jul 16, 2026

@Andezion Andezion left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Look good to me!

"sec-websocket-version: 13\r\n\r\n";

my_rbuf = tal_strdup(tmpctx, hdr);
my_rbuf_off = 0;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

@Andezion
Andezion force-pushed the connectd-ws-case-insensitive-headers branch from ff22cee to 5710e47 Compare July 17, 2026 08:16
Comment thread connectd/websocketd.c Outdated
Comment thread connectd/websocketd.c Outdated
@coreyphillips
coreyphillips force-pushed the connectd-ws-case-insensitive-headers branch from 5710e47 to a523a9d Compare July 22, 2026 15:50
HTTP header field names are case-insensitive (RFC 9110 section 5.1) and
RFC 6455 says the Upgrade and Connection values are treated as ASCII
case-insensitive, as the comment in websocketd.c already quotes. The
handshake parser matched header names byte-exactly and the values with
case-sensitive strstr, so any client that normalizes header casing got
400: notably Node.js's built-in WebSocket (undici) lowercases all
request headers and can never connect to a bind-addr=ws: listener,
while browsers happen to send RFC casing and work.

Match header names case-insensitively in get_http_hdr and use a
case-insensitive search for the Upgrade and Connection values. The
Sec-WebSocket-Version value comparison stays exact and the key is
base64 data, unchanged. Extends the unit test with a lowercased
handshake as sent by Node.

Fixes ElementsProject#9307

Changelog-Fixed: connectd: the WebSocket port now accepts handshakes from clients that send lowercase HTTP header names, such as Node.js's built-in WebSocket.
Signed-off-by: Corey Phillips <corey.lyle.phillips@proton.me>
@coreyphillips
coreyphillips force-pushed the connectd-ws-case-insensitive-headers branch from a523a9d to 3e63246 Compare July 23, 2026 02:49
@coreyphillips
coreyphillips requested a review from cdecker July 23, 2026 02:53
@madelinevibes madelinevibes added this to the v26.09 milestone Jul 31, 2026
@daywalker90
daywalker90 requested a review from Andezion August 17, 2026 12:19
@daywalker90
daywalker90 removed the request for review from cdecker August 26, 2026 14:21
@daywalker90
daywalker90 merged commit f0c702e into ElementsProject:master Aug 26, 2026
45 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

connectd websocket: HTTP handshake headers matched case-sensitively, rejecting RFC-compliant clients

5 participants