Skip to content

fix(network): do not split single-valued and http-date headers on comma - #42723

Open
Mohan Ram (mohanram-dev) wants to merge 1 commit into
microsoft:mainfrom
mohanram-dev:fix/preserve-single-valued-headers
Open

Mohan Ram (mohanram-dev) wants to merge 1 commit into
microsoft:mainfrom
mohanram-dev:fix/preserve-single-valued-headers

Conversation

@mohanram-dev

Copy link
Copy Markdown

Description

Fixes #42687.

On Firefox and WebKit, response headers are provided joined or parsed through internal comma splitting (ffNetworkManager.ts and headersObjectToArray).

Per RFC 9110 §5.3, field lines containing an HTTP-date (Date, Expires, Last-Modified, If-Modified-Since, If-Unmodified-Since, Retry-After) and standard single-valued headers (Location, Content-Type, Content-Disposition, etc.) are not comma-separated lists. Splitting on , corrupted every date header (e.g., splitting "Wed, 21 Oct 2026 07:28:00 GMT" into "Wed" and "21 Oct 2026 07:28:00 GMT"). Additionally, on macOS WebKit where wkSetCookieSeparator = ',', cookies with Expires attributes containing commas were being split within the date string.

This PR:

  1. Defines singleValuedHeaders Set in packages/isomorphic/headers.ts containing standard single-valued and HTTP-date header names.
  2. Updates headersObjectToArray to preserve single-valued headers intact without splitting on ,.
  3. Adds splitSetCookieString to safely handle comma-separated Set-Cookie headers while preserving dates inside Expires=... attributes.
  4. Updates ffNetworkManager.ts (parseMultivalueHeaders) to avoid splitting single-valued and date headers on commas.
  5. Adds comprehensive unit tests (tests/library/unit/headers.spec.ts) and end-to-end response header tests (tests/page/page-network-response.spec.ts).

@ayaangazali

Copy link
Copy Markdown

Reporter of #42687 here. Ran the reproducer from the issue against this branch on all three engines, and it fixes every case I filed.

chromium  last-modified -> [{"last-modified","Wed, 21 Oct 2026 07:28:00 GMT"}]   date count 1
firefox   last-modified -> [{"last-modified","Wed, 21 Oct 2026 07:28:00 GMT"}]   date count 1
webkit    last-modified -> [{"Last-Modified","Wed, 21 Oct 2026 07:28:00 GMT"}]   date count 1

Set-Cookie with an Expires date is a single correct entry on all three now, and allHeaders()['set-cookie'] no longer comes back with the comma turned into a newline on macOS WebKit, which was the darwin-only half.

I also checked the thing I was worried about when I filed it, since the split existed to recover headers the protocol had already joined. No regression there:

2 Set-Cookie sent -> ["a=1; Path=/","b=2; Path=/"]   on all three
2 x-multi sent    -> ["m1","m2"]                     on all three

One residual difference, which I do not think is yours to fix but is worth knowing the boundary of. A single genuinely list-valued header still splits on the two non-Chromium engines:

sent once: cache-control: no-cache, no-store
chromium -> ["no-cache, no-store"]
firefox  -> ["no-cache","no-store"]
webkit   -> ["no-cache","no-store"]

That is the ambiguity I mentioned on the issue rather than a new problem: once the protocol has joined repeated headers into one string, nothing downstream can tell one comma-list header from two repeated ones, so some guess is unavoidable. Your allowlist removes the cases where the guess is provably wrong, which is the part that was actually corrupting data. Just flagging it so a reviewer is not surprised that chromium and the others still differ on that one shape.

Nice work on this, the RFC 9110 framing is a much better justification than the "exclude the date headers" hand-wave I had in the issue.

@mohanram-dev

Copy link
Copy Markdown
Author

Thanks Ayaan Gazali (@ayaangazali) for testing and verifying across all three engines! Seeing that Devin Rousso (@dcrousso) opened #42734 with the minimal splitHeaderValue approach (already approved and passed CI), I will close this PR once #42734 is merged into main.

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.

[Bug]: headersArray() splits single header values on commas on Firefox and WebKit, corrupting every HTTP-date header

2 participants