5.4. Main Algorithms
5.4.1. Parse and Store a Cookie
To Parse and Store a Cookie given a byte sequence input, boolean isSecure, domain or IP address host, URL path path, boolean httpOnlyAllowed, boolean allowNonHostOnlyCookieForPublicSuffix, and boolean sameSiteStrictOrLaxAllowed:¶
5.4.2. Parse a Cookie
To Parse a Cookie given a byte sequence input, boolean isSecure, host host, URL path path, run these steps. They return a new cookie or failure:¶
-
If input contains a byte in the range 0x00 to 0x08, inclusive, the range 0x0A to 0x1F inclusive, or 0x7F (CTL bytes excluding HTAB), then return failure.¶
-
Let nameValueInput be null.¶
-
Let attributesInput be the empty byte sequence.¶
-
If input contains 0x3B (;), then set nameValueInput to the bytes up to, but not including, the first 0x3B (;), and attributesInput to the remainder of input (including the 0x3B (;) in question).¶
-
Otherwise, set nameValueInput to input.¶
-
Assert: nameValueInput is a byte sequence.¶
-
Let name be null.¶
-
Let value be null.¶
-
If nameValueInput does not contain a 0x3D (=) character, then set name to the empty byte sequence, and value to nameValueInput.¶
-
Otherwise, set name to the bytes up to, but not including, the first 0x3D (=), and set value to the bytes after the first 0x3D (=) (possibly being the empty byte sequence).¶
-
Remove any leading or trailing WSP bytes from name and value.¶
-
If name's length + value's length is 0 or is greater than 4096, then return failure.¶
-
Let cookie be a new cookie whose name is name and value is value.¶
-
Set cookie's path to the result of running Cookie Default Path with path.¶
Note: A
Path
attribute can override this.¶ -
While attributesInput is not an empty byte sequence:¶
-
Let maxAgeSeen be false.¶
-
Let char be the result of consuming the first byte of attributesInput.¶
-
Assert: char is 0x3B (;).¶
-
Let attributeNameValueInput be null.¶
-
If attributesInput contains 0x3B (;), then set attributeNameValueInput to the result of consuming the bytes of attributesInput up to, but not including, the first 0x3B (;).¶
-
Otherwise, set attributeNameValueInput to the result of consuming the remainder of attributesInput.¶
-
Let attributeName be null.¶
-
Let attributeValue be the empty string.¶
-
If attributeNameValueInput contains a 0x3D (=), then set attributeName to the bytes up to, but not including, the first 0x3D (=) of attributeNameValueInput, and attributeValue to the bytes after the first 0x3D (=) of attributeNameValueInput.¶
-
Otherwise, set attributeName to attributeNameValueInput.¶
-
Remove any leading or trailing WSP bytes from attributeName and attributeValue.¶
-
If attributeValue's length is greater than 1024, then continue.¶
-
If attributeName is a byte-case-insensitive match for
Expires
:¶-
If maxAgeSeen is true, then continue.¶
-
Let expiryTime be the result of running Parse a Date given attributeValue.¶
-
If attributeValue is failure, then continue.¶
-
If expiryTime is greater than the current time and date + the user agent's cookie age limit, then set expiryTime to the user agent's cookie age limit.¶
-
If expiryTime is earlier than the earliest date the user agent can represent, the user agent MAY replace expiryTime with the earliest representable date.¶
-
Set cookie's expiry-time to expiryTime.¶
-
-
If attributeName is a byte-case-insensitive match for
Max-Age
:¶-
If attributeValue is empty, continue.¶
-
If the first byte of attributeValue is neither a DIGIT, nor 0x2D (-) followed by a DIGIT, then continue.¶
-
If the remainder of attributeValue contains a non-DIGIT, then continue.¶
-
Let deltaSeconds be attributeValue, converted to a base 10 integer.¶
-
Set deltaSeconds to the smaller of deltaSeconds and the user agent's cookie age limit, in seconds.¶
-
If deltaSeconds is less than or equal to 0, let expiryTime be the earliest representable date and time. Otherwise, let expiryTime be the current date and time + deltaSeconds seconds.¶
-
Set cookie's expiry-time to expiryTime.¶
-
Set maxAgeSeen to true.¶
-
-
If attributeName is a byte-case-insensitive match for
Domain
:¶ -
If attributeName is a byte-case-insensitive match for
Path
:¶-
If attributeValue is not empty and if the first byte of attributeValue is 0x2F (/), then set cookie's path to attributeValue split on 0x2F (/).¶
-
-
If attributeName is a byte-case-insensitive match for
Secure
:¶-
Set cookie's secure to true.¶
-
-
If attributeName is a byte-case-insensitive match for
HttpOnly
:¶-
Set cookie's http-only to true.¶
-
-
If attributeName is a byte-case-insensitive match for
SameSite
:¶-
If attributeValue is a byte-case-insensitive match for
None
, then set cookie's same-site to "none".¶ -
If attributeValue is a byte-case-insensitive match for
Strict
, then set cookie's same-site to "strict".¶ -
If attributeValue is a byte-case-insensitive match for
Lax
, then set cookie's same-site to "lax".¶
-
-
-
Return cookie.¶
Note: Attributes with an unrecognized attributeName are ignored.¶
Note: This intentionally overrides earlier cookie attributes so that generally the last specified cookie attribute "wins".¶
5.4.3. Store a Cookie
To Store a Cookie given a cookie cookie, boolean isSecure, domain or IP address host, boolean httpOnlyAllowed, boolean allowNonHostOnlyCookieForPublicSuffix, and boolean sameSiteStrictOrLaxAllowed:¶
-
Assert: cookie's name's length + cookie's value's length is not 0 or greater than 4096.¶
-
Assert: cookie's name does not contain a byte in the range 0x00 to 0x08, inclusive, in the range 0x0A to 0x1F, inclusive, or 0x7F (CTL characters excluding HTAB).¶
-
If cookie's host is failure, then return.¶
-
Set cookie's creation-time and last-access-time to the current date and time.¶
-
If allowNonHostOnlyCookieForPublicSuffix is false and cookie's host is a public suffix:¶
Note: This step prevents
attacker.example
from disrupting the integrity ofsite.example
by setting a cookie with aDomain
attribute ofexample
. In the event the end user navigates directly toexample
, a cookie can still be set and will forcibly have its host-only set to true.¶ -
If cookie's host is null:¶
-
Otherwise:¶
-
Assert: cookie's host is a domain or IP address.¶
-
If httpOnlyAllowed is false and cookie's http-only is true, then return.¶
-
If isSecure is false:¶
-
If cookie's secure-only is true, then return.¶
-
If the user agent's cookie store contains at least one cookie existingCookie that meets all of the following criteria:¶
-
existingCookie's name is cookie's name;¶
-
existingCookie's secure-only is true;¶
-
existingCookie's host Domain-Matches cookie's host, or vice-versa; and¶
-
cookie's path Path-Matches existingCookie's path,¶
then return.¶
Note: The path comparison is not symmetric, ensuring only that a newly-created, non-secure cookie does not overlay an existing secure cookie, providing some mitigation against cookie-fixing attacks. That is, given an existing secure cookie named 'a' with a path of '/login', a non-secure cookie named 'a' could be set for a path of '/' or '/foo', but not for a path of '/login' or '/login/en'.¶
-
-
-
If cookie's same-site is not "
none
" and sameSiteStrictOrLaxAllowed is false, then return.¶ -
If cookie's same-site is "
none
" and cookie's secure-only is false, then return.¶ -
If cookie's name, byte-lowercased, starts with
__secure-
and cookie's secure-only is false, then return.¶Note: The check here and those below are with a byte-lowercased value in order to protect servers that process these values in a case-insensitive manner.¶
-
If cookie's name, byte-lowercased, starts with
__host-
and not all of the following are true:¶-
cookie's secure-only is true;¶
-
cookie's host-only is true; and¶
-
cookie's path's size is 1 and cookie's path[0] is the empty string,¶
then return.¶
-
-
If cookie's name is the empty byte sequence and one of the following is true:¶
-
cookie's value, byte-lowercased, starts with
__secure-
, or¶ -
cookie's value, byte-lowercased, starts with
__host-
¶
then return.¶
-
-
If the user agent's cookie store contains a cookie oldCookie whose name is cookie's name, host is host-equal to cookie's host, host-only is cookie's host-only, and path is path-equal to cookie's path:¶
-
If httpOnlyAllowed is false and oldCookie's http-only is true, then return.¶
-
Set cookie's creation-time to oldCookie's creation-time.¶
-
Remove oldCookie from the user agent's cookie store.¶
Note: This algorithm maintains the invariant that there is at most one such cookie.¶
-
-
Insert cookie into the user agent's cookie store.¶
-
Remove all expired cookies from the user agent's cookie store.¶
-
Run Remove Excess Cookies for Host given cookie's host.¶
-
Run Remove Global Excess Cookies.¶
5.4.4. Retrieve Cookies
To Retrieve Cookies given a boolean isSecure, host host, URL path path, boolean httpOnlyAllowed, and string sameSite:¶
-
Assert: sameSite is "
strict-or-less
", "lax-or-less
", "unset-or-less
", or "none
".¶ -
Let cookies be all cookies from the user agent's cookie store that meet these conditions:¶
-
One of the following is true:¶
-
cookie's host-only is true and host is host-equal to cookie's host, or¶
-
cookie's host-only is false and host Domain-Matches cookie's host.¶
It's possible that the public suffix list changed since a cookie was created. If this change results in a cookie's host becoming a public suffix and the cookie's host-only is false, then that cookie SHOULD NOT be returned.¶
XXX: We should probably move this requirement out-of-bound as this invalidation should happen as part of updating the public suffixes.¶
-
-
path Path-Matches cookie's path.¶
-
One of the following is true:¶
-
One of the following is true:¶
-
One of the following is true:¶
-
-
Sort cookies in the following order:¶
-
Set the last-access-time of each cookie of cookies to the current date and time and reflect these changes in the user agent's cookie store.¶
-
Return cookies.¶