Skip to content

fix(net): canonicalize the cookie domain on every jar key - #649

Open
aech wants to merge 1 commit into
h4ckf0r0day:mainfrom
aech:fix/cdp-cookie-domain-leading-dot
Open

fix(net): canonicalize the cookie domain on every jar key#649
aech wants to merge 1 commit into
h4ckf0r0day:mainfrom
aech:fix/cdp-cookie-domain-leading-dot

Conversation

@aech

@aech aech commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Fixes #648

What changed

Network.setCookies retained the leading dot and the letter case, while the Set-Cookie path stripped the dot. The same cookie, when set via both entrances, resulted in two jar entries, and both were sent out in a single request. RFC 6265 4.1.2.3 ignores the dot, and hosts are case-insensitive. A helper therefore now constructs every jar key: the CDP import, the Set-Cookie path, and the JS path, both deletion paths, and the MCP domain filter. This also eliminates three copies of a search across three different spellings, which existed solely to mask the inconsistency.

domain_matches retains its comparison without allocation. It sits on the per-request path and ignores dot and case anyway.

load_from_file imports via set_cookies_from_cdp, so a persisted store with dotted domains is repaired on load.

Validation

cargo nextest run --release --features render --no-fail-fast                  1411 passed
cargo nextest run --release --features render,stealth --no-fail-fast     1413/1414 passed
cargo nextest run --release --no-default-features -p obscura-net -p obscura-mcp  99 passed
cargo build --release -p obscura-cli --bins --features render                   clean
cargo build --release -p obscura-cli --bins --features render,stealth           clean
cargo build --release -p obscura-cli --bins --no-default-features               clean
obstacle course, --runs 1 --warmup 0                                            32/33

The stealth run is included because wreq_client.rs uses the same cookie jar and calls set_cookie. It therefore exercises the changed path.

Five tests in cookies.rs cover the defect. Each was tested against an intentionally broken version:

  • Storing the raw domain in entry.domain causes test_cdp_stored_domain_field_carries_no_dot to fail
  • Failing to canonicalize one of the deletion paths causes test_cdp_zero_expiry_deletes_across_domain_spellings and test_delete_cookie_canonicalizes_its_lookup to fail

Two failures also occur on main and are not caused by this change:

  • The obstacle course stage observer-intersection (expected 'io:50', got ''). The remaining 32 pass.
  • wreq_client::tests::stealth_client_decodes_gzip_response. Its fixture listens on 127.0.0.1, and the SSRF guard blocks this unless OBSCURA_ALLOW_PRIVATE_NETWORK is set. If it is set, client::ssrf_tests::validate_url_blocks_unspecified_and_allows_public fails instead, because it requires that 0.0.0.0 be rejected. Both were measured against main at 94374e6.

Rendering

Not applicable.

Performance

get_cookie_header and domain_matches, the per-request path, remain unaffected. The change adds one allocation per cookie on import and one per delete call. Median latency of the obstacle course: 3034.2 ms with the change, 3030.5 ms on main, inside the noise floor.

Checklist

  • The change is focused and does not remove existing behavior without justification.
  • Tests cover the failure or feature.
  • Existing tests pass, including render and no-render configurations when affected.
  • I checked for CPU, latency, and memory regressions.
  • Public API or user-facing behavior changes are documented.

Network.setCookies kept a leading dot and the letter case, the Set-Cookie path
stripped the dot. The same cookie arriving over both entrances became two jar
entries and both went out in one request. RFC 6265 4.1.2.3 ignores the dot and
hosts are case-insensitive, so one helper now builds every key: the CDP import,
the Set-Cookie and JS paths, both delete paths, and the MCP domain filter.

domain_matches keeps its allocation-free comparison, it is on the per-request
path and already ignores dot and case.

load_from_file imports through set_cookies_from_cdp, so a persisted store with
dotted domains is repaired on load.

Fixes h4ckf0r0day#648.
@SGavrl SGavrl closed this Aug 14, 2026
@SGavrl SGavrl reopened this Aug 14, 2026
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.

CDP import and Set-Cookie normalize the domain differently, the same cookie sits twice in the jar

2 participants