From d917728053e8fd50b18f2582d8868deb618ebd47 Mon Sep 17 00:00:00 2001 From: NYCU-Chung Date: Mon, 6 Apr 2026 20:39:56 +0800 Subject: [PATCH] fix(cookie): reject Set-Cookie domains that are public suffixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit parseDomain() rejects bare TLDs (e.g. Domain=.io) but accepts multi-level public suffixes like .co.uk, .com.au, .co.jp. Per RFC 6265bis §5.7.3.10, user agents should reject cookies whose domain attribute is a public suffix. Chrome, Firefox, and Safari all enforce this using the Public Suffix List. The PSL data is already imported (Cookie.zig:26) and used in findSecondLevelDomain(), but parseDomain() does not consult it. This causes behavior differences vs Chrome when automating .co.uk / .com.au / .co.jp sites via CDP — cookies that Chrome silently drops are accepted by Lightpanda, polluting the cookie jar across unrelated sites in the same session. --- src/browser/webapi/storage/Cookie.zig | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/browser/webapi/storage/Cookie.zig b/src/browser/webapi/storage/Cookie.zig index 649a04ccd0..4616b3c587 100644 --- a/src/browser/webapi/storage/Cookie.zig +++ b/src/browser/webapi/storage/Cookie.zig @@ -273,6 +273,12 @@ pub fn parseDomain(arena: Allocator, url_: ?[:0]const u8, explicit_domain: ?[]co // can't set a cookie for a TLD return error.InvalidDomain; } + + // Can't set a cookie for a public suffix (e.g. co.uk, com.au). + if (public_suffix_list(owned_domain[1..])) { + return error.InvalidDomain; + } + if (encoded_host) |host| { if (std.mem.endsWith(u8, host, owned_domain[1..]) == false) { return error.InvalidDomain; @@ -1027,6 +1033,15 @@ test "Cookie: parse domain" { try expectError(error.InvalidDomain, "http://lightpanda.io/", "b;domain=other.lightpanda.io"); try expectError(error.InvalidDomain, "http://lightpanda.io/", "b;domain=other.lightpanda.com"); try expectError(error.InvalidDomain, "http://lightpanda.io/", "b;domain=other.example.com"); + + // Public suffixes should be rejected (test PSL entries: "gov.uk", "api.gov.uk") + try expectError(error.InvalidDomain, "http://example.gov.uk/", "b;domain=gov.uk"); + try expectError(error.InvalidDomain, "http://example.gov.uk/", "b;domain=.gov.uk"); + try expectError(error.InvalidDomain, "http://test.api.gov.uk/", "b;domain=api.gov.uk"); + + // Subdomains of public suffixes should still be accepted + try expectAttribute(.{ .domain = ".example.gov.uk" }, "http://example.gov.uk/", "b;domain=example.gov.uk"); + try expectAttribute(.{ .domain = ".example.gov.uk" }, "http://sub.example.gov.uk/", "b;domain=example.gov.uk"); } test "Cookie: parse limit" {