LibHTTP: Validate direct cookie conversion

DevTools edits cookies as concrete fields rather than Set-Cookie
strings. Validate direct Cookie objects while converting them back to
ParsedCookie so invalid edits can be reported without making the RFC
storage algorithm stricter.
This commit is contained in:
Sam Atkins 2026-06-17 16:16:22 +01:00 committed by Jelle Raaijmakers
parent 680dc78dac
commit 953251351d

View file

@ -103,6 +103,44 @@ Optional<ParsedCookie> parse_cookie(URL::URL const& url, StringView cookie_strin
ErrorOr<ParsedCookie> parse_cookie(Cookie const& cookie) ErrorOr<ParsedCookie> parse_cookie(Cookie const& cookie)
{ {
if (cookie.name.is_empty() && cookie.value.is_empty())
return Error::from_string_literal("Cookie name and value cannot both be empty");
if (cookie_contains_invalid_control_character(cookie.name))
return Error::from_string_literal("Cookie name contains an invalid control character");
if (cookie_contains_invalid_control_character(cookie.value))
return Error::from_string_literal("Cookie value contains an invalid control character");
if (cookie.name.byte_count() + cookie.value.byte_count() > 4096)
return Error::from_string_literal("Cookie name and value exceed the maximum size");
if (!cookie.path.bytes_as_string_view().starts_with("/"sv))
return Error::from_string_literal("Cookie path must start with /");
if (cookie.path.byte_count() > 1024)
return Error::from_string_literal("Cookie path exceeds the maximum size");
if (cookie.same_site == SameSite::None && !cookie.secure)
return Error::from_string_literal("SameSite=None cookies must be secure");
if (cookie.name.starts_with_bytes("__Secure-"sv, CaseSensitivity::CaseInsensitive) && !cookie.secure)
return Error::from_string_literal("__Secure- cookies must be secure");
if (cookie.name.starts_with_bytes("__Host-"sv, CaseSensitivity::CaseInsensitive)) {
if (!cookie.secure)
return Error::from_string_literal("__Host- cookies must be secure");
if (!cookie.host_only)
return Error::from_string_literal("__Host- cookies must be host-only");
if (cookie.path != "/"sv)
return Error::from_string_literal("__Host- cookies must use path /");
}
if (cookie.name.is_empty()) {
if (cookie.value.starts_with_bytes("__Secure-"sv, CaseSensitivity::CaseInsensitive))
return Error::from_string_literal("__Secure- cookies must have a name");
if (cookie.value.starts_with_bytes("__Host-"sv, CaseSensitivity::CaseInsensitive))
return Error::from_string_literal("__Host- cookies must have a name");
}
ParsedCookie parsed_cookie; ParsedCookie parsed_cookie;
parsed_cookie.name = cookie.name; parsed_cookie.name = cookie.name;
parsed_cookie.value = cookie.value; parsed_cookie.value = cookie.value;
@ -111,6 +149,9 @@ ErrorOr<ParsedCookie> parse_cookie(Cookie const& cookie)
parsed_cookie.secure_attribute_present = cookie.secure; parsed_cookie.secure_attribute_present = cookie.secure;
parsed_cookie.http_only_attribute_present = cookie.http_only; parsed_cookie.http_only_attribute_present = cookie.http_only;
if (!cookie.host_only && cookie.domain.byte_count() > 1024)
return Error::from_string_literal("Cookie host exceeds the maximum size");
if (!cookie.host_only) if (!cookie.host_only)
TRY(on_domain_attribute(parsed_cookie, cookie.domain.bytes_as_string_view())); TRY(on_domain_attribute(parsed_cookie, cookie.domain.bytes_as_string_view()));