@@ -54,10 +54,24 @@ urlPrefix:https://tc39.es/ecma262/#;type:dfn;spec:ecma-262
5454 url:realm;text:realm
5555 url:sec-list-and-record-specification-type;text:Record
5656 url:current-realm;text:current realm
57+
58+ urlPrefix:https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-layered-cookies#;type:dfn;spec:cookies
59+ url:name-cookie-store-and-limits;text:cookie store
60+ url:name-parse-and-store-a-cookie;text:parse and store a cookie
61+ url:name-parse-a-cookie;text:parse a cookie
62+ url:name-store-a-cookie;text:store a cookie
63+ url:name-retrieve-cookies;text:retrieve cookies
64+ url:name-serialize-cookies;text:serialize cookies
65+ url:name-garbage-collect-cookies;text:garbage collect cookies
5766</pre>
5867
5968<pre class=biblio>
6069{
70+ "COOKIES": {
71+ "authors": ["Johann Hofmann", "Anne van Kesteren"] ,
72+ "href": "https://httpwg.org/http-extensions/draft-ietf-httpbis-layered-cookies.html",
73+ "title": "Cookies: HTTP State Management Mechanism"
74+ },
6175 "HTTP": {
6276 "aliasOf": "RFC9110"
6377 },
@@ -1965,6 +1979,10 @@ not always relevant and might require different behavior.
19651979<a lt=fetch for=/>fetching</a> . It provides a convenient way for standards to not have to set
19661980<a for=/>request</a> 's <a for=request>origin</a> .
19671981
1982+ <p> A <a for=/>request</a> has an associated
1983+ <dfn export for=request>top-level navigation initiator origin</dfn> , which is an <a for=/>origin</a>
1984+ or null. Unless stated otherwise it is null.
1985+
19681986<p> A <a for=/>request</a> has an associated
19691987<dfn export for=request id=concept-request-policy-container>policy container</dfn> , which is
19701988"<code> client</code> " or a <a for=/>policy container</a> . Unless stated otherwise it is
@@ -2249,31 +2267,39 @@ or "<code>object</code>".
22492267<hr>
22502268
22512269<div algorithm>
2252- < p > A < a for =/ > request</ a > < var > request</ var > has a
2253- < dfn for =request id = concept-request-tainted-origin > redirect-tainted origin </ dfn > if these steps
2254- return true:
2270+ <p> To compute the <dfn for=request id=concept- request-tainted-origin>redirect-taint</dfn> of a
2271+ <a for=/> request</a> <var> request </var> , perform the following steps. They return
2272+ " <code> same-origin </code> ", " <code> same-site </code> ", or " <code> cross-site </code> ".
22552273
22562274<ol>
22572275 <li><p> <a for=/>Assert</a> : <var> request</var> 's <a for=request>origin</a> is not
22582276 "<code> client</code> ".
22592277
22602278 <li><p> Let <var> lastURL</var> be null.
22612279
2280+ <li><p> Let <var> taint</var> be "<code> same-origin</code> ".
2281+
22622282 <li>
22632283 <p> <a for=list>For each</a> <var> url</var> of <var> request</var> 's <a for=request>URL list</a> :
22642284
22652285 <ol>
22662286 <li><p> If <var> lastURL</var> is null, then set <var> lastURL</var> to <var> url</var> and
22672287 <a for=iteration>continue</a> .
22682288
2289+ <li><p> If <var> url</var> 's <a for=url>origin</a> is not <a for=/>same site</a> with
2290+ <var> lastURL</var> 's <a for=url>origin</a> and <var>request</var>' s <a for=request>origin</a> is
2291+ not <a for=/>same site</a> with <var> lastURL</var> 's <a for=url>origin</a> , then return
2292+ "<code> cross-site</code> ".
2293+
22692294 <li><p> If <var> url</var> 's <a for=url>origin</a> is not <a>same origin</a> with
22702295 <var> lastURL</var> 's <a for=url>origin</a> and <var>request</var>' s <a for=request>origin</a> is
2271- not < a > same origin</ a > with < var > lastURL</ var > 's < a for =url > origin</ a > , then return true.
2296+ not <a>same origin</a> with <var> lastURL</var> 's <a for=url>origin</a> , then set
2297+ <var> taint</var> to "<code> same-site</code> ".
22722298
2273- < li > Set < var > lastURL</ var > to < var > url</ var > .
2299+ <li><p> Set <var> lastURL</var> to <var> url</var> .
22742300 </ol>
22752301
2276- < li > Return false .
2302+ <li><p> Return <var> taint </var> .
22772303</ol>
22782304</div>
22792305
@@ -2285,8 +2311,8 @@ run these steps:
22852311 <li><p> <a for=/>Assert</a> : <var> request</var> 's <a for=request>origin</a> is not
22862312 "<code> client</code> ".
22872313
2288- < li > < p > If < var > request</ var > has a < a for =request > redirect-tainted origin </ a > , then return
2289- "< code > null</ code > ".
2314+ <li><p> If <var> request</var> 's <a for=request>redirect-taint </a> is not " <code> same-origin </code> ",
2315+ then return "<code> null</code> ".
22902316
22912317 <li><p> Return <var> request</var> 's <a for=request>origin</a> ,
22922318 <a lt="ASCII serialization of an origin">serialized</a> .
@@ -2385,20 +2411,20 @@ source of security bugs. Please seek security review for features that deal with
23852411 "<code> client</code> ".
23862412
23872413 <li><p> If <var> request</var> 's <a for=request>mode</a> is not "<code> no-cors</code> ", then return
2388- true.</ p >
2414+ true.
23892415
2390- < li > < p > If < var > request</ var > 's < a for =request > client</ a > is null, then return true.</ p >
2416+ <li><p> If <var> request</var> 's <a for=request>client</a> is null, then return true.
23912417
23922418 <li><p> If <var> request</var> 's <a for=request>client</a>' s
23932419 <a for="environment settings object">policy container</a> 's
23942420 <a for="policy container">embedder policy</a> 's <a for="embedder policy">value</a> is not
2395- "< a for ="embedder policy value "> < code > credentialless</ code > </ a > ", then return true.</ p >
2421+ "<a for="embedder policy value"><code>credentialless</code></a> ", then return true.
23962422
23972423 <li><p> If <var> request</var> 's <a for=request>origin</a> is <a>same origin</a> with
2398- < var > request</ var > 's < a for =request > current URL</ a > 's < a for =url > origin</ a > and < var > request</ var >
2399- does not have a < a for =request > redirect-tainted origin</ a > , then return true.</ p >
2424+ <var> request</var> 's <a for=request>current URL</a>' s <a for=url>origin</a> and <var> request</var> 's
2425+ <a for=request>redirect-taint</a> is not " <code> same- origin</code> " , then return true.
24002426
2401- < li > < p > Return false.</ p >
2427+ <li><p> Return false.
24022428</ol>
24032429</div>
24042430
@@ -2509,8 +2535,9 @@ this is also tracked internally using the request's <a for=request>timing allow
25092535<dfn export for=response>service worker timing info</dfn> (null or a
25102536<a for=/>service worker timing info</a> ), which is initially null.
25112537
2512- < p > A < a for =/ > response</ a > has an associated < dfn for =response > has-cross-origin-redirects</ dfn >
2513- (a boolean), which is initially false.
2538+ <p> A <a for=/>response</a> has an associated <dfn for=response>redirect taint</dfn>
2539+ ("<code> same-origin</code> ", "<code> same-site</code> ", or "<code> cross-site</code> "), which is
2540+ initially "<code> same-origin</code> ".
25142541
25152542<hr>
25162543
@@ -3315,6 +3342,127 @@ through TLS using ALPN. The protocol cannot be spoofed through HTTP requests in
33153342
33163343<h2 id=http-extensions>HTTP extensions</h2>
33173344
3345+ <h3 id=cookies>Cookies</h3>
3346+
3347+ <p> The `<code> Cookie</code> ` request header and `<code> Set-Cookie</code> ` response headers are
3348+ largely defined in their own specifications. We define additional infrastructure to be able to use
3349+ them conveniently here. [[COOKIES]] .
3350+
3351+
3352+ <h4 id=cookie-header>`<code>Cookie</code>` header</h4>
3353+
3354+ <div algorithm>
3355+ <p> To <dfn>append a request `<code>Cookie</code>` header</dfn> , given a <a for=/>request</a>
3356+ <var> request</var> :
3357+
3358+ <ol>
3359+ <li><p> If the user agent is configured to disable cookies for <var> request</var> , then it should
3360+ return.
3361+
3362+ <li><p> Let |sameSite| be the result of [=determining the same-site mode=] for <var> request</var> .
3363+
3364+ <li><p> Let |isSecure| be true if <var> request</var> 's <a for=request>current URL</a>' s
3365+ <a for=url>scheme</a> is "<code> https</code> "; otherwise false.
3366+
3367+ <li>
3368+ <p> Let |httpOnlyAllowed| be true.
3369+
3370+ <p class=note> True follows from this being invoked from <a>fetch</a> , as opposed to the
3371+ <code> document.cookie</code> getter steps for instance.
3372+
3373+ <li>
3374+ <p> Let |cookies| be the result of running <a>retrieve cookies</a> given |isSecure|,
3375+ <var> request</var> 's <a for=request>current URL</a>' s <a for=url>host</a> , <var> request</var> 's
3376+ <a for=request>current URL</a> 's <a for=url>path</a> , |httpOnlyAllowed|, and |sameSite|.
3377+
3378+ <p class=note> The cookie store returns an ordered list of cookies
3379+
3380+ <li><p> If |cookies| <a for="list">is empty</a> , then return.
3381+
3382+ <li><p> Let |value| be the result of running <a>serialize cookies</a> given |cookies|.
3383+
3384+ <li><p> <a for="header list">Append</a> (`<code> Cookie</code> `, <var> value</var> ) to
3385+ <var> request</var> 's <a for=request>header list</a> .
3386+ </ol>
3387+ </div>
3388+
3389+
3390+ <h4 id=set-cookie-header>`<code>Set-Cookie</code>` header</h4>
3391+
3392+ <div algorithm>
3393+ <p> To <dfn>parse and store response `<code>Set-Cookie</code>` headers</dfn> , given a
3394+ <a for=/>request</a> <var> request</var> and a <a for=/>response</a> <var> response</var> :
3395+
3396+ <ol>
3397+ <li><p> If the user agent is configured to disable cookies for <var> request</var> , then it should
3398+ return.
3399+
3400+ <li><p> Let |allowNonHostOnlyCookieForPublicSuffix| be false.
3401+
3402+ <li><p> Let |isSecure| be true if <var> request</var> 's <a for=request>current URL</a>' s
3403+ <a for=url>scheme</a> is "<code> https</code> "; otherwise false.
3404+
3405+ <li>
3406+ <p> Let |httpOnlyAllowed| be true.
3407+
3408+ <p class=note> True follows from this being invoked from <a>fetch</a> , as opposed to the
3409+ <code> document.cookie</code> getter steps for instance.
3410+
3411+ <li><p> Let |sameSiteStrictOrLaxAllowed| be true if the result of [=determine the same-site mode=]
3412+ for |request| is "<code> strict-or-less</code> "; otherwise false.
3413+
3414+ <li>
3415+ <p> <a for=list>For each</a> <var> header</var> of <var> response</var> 's
3416+ <a for=response>header list</a> :
3417+
3418+ <ol>
3419+ <li><p> If <var> header</var> 's <a for=header>name</a> is not a <a>byte-case-insensitive</a> match
3420+ for `<code> Set-Cookie</code> `, then <a for=iteration>continue</a> .
3421+
3422+ <li><p> <a>Parse and store a cookie</a> given <var> header</var> 's <a for=header>value</a> ,
3423+ |isSecure|, <var> request</var> 's <a for=request>current URL</a>' s <a for=url>host</a> ,
3424+ <var> request</var> 's <a for=request>current URL</a>' s <a for=url>path</a> , |httpOnlyAllowed|,
3425+ |allowNonHostOnlyCookieForPublicSuffix|, and |sameSiteStrictOrLaxAllowed|.
3426+
3427+ <li><p> <a>Garbage collect cookies</a> given <var> request</var> 's <a for=request>current URL</a>' s
3428+ <a for=url>host</a> .
3429+ </ol>
3430+
3431+ <p class=note> As noted elsewhere the `<code> Set-Cookie</code> ` header cannot be combined and
3432+ therefore each occurrence is processed independently. This is not allowed for any other header.
3433+ </ol>
3434+ </div>
3435+
3436+
3437+ <h4 id=cookie-infrastructure>Cookie infrastructure</h4>
3438+
3439+ <div algorithm>
3440+ <p> To <dfn>determine the same-site mode</dfn> for a given <a for=/>request</a> <var> request</var> :
3441+
3442+ <ol>
3443+ <li><p> <a for=/>Assert</a> : <var> request</var> 's <a for=request>method</a> is "<code> GET</code> "
3444+ or "<code> POST</code> ".
3445+
3446+ <li><p> If <var> request</var> 's <a for=request>top-level navigation initiator origin</a> is not
3447+ null and is not <a for=/>same site</a> with <var> request</var> 's <a for=request>URL</a>' s
3448+ <a for=url>origin</a> , then return "<code> unset-or-less</code> ".
3449+
3450+ <li><p> If <var> request</var> 's <a for=request>method</a> is "<code> GET</code> " and
3451+ <var> request</var> 's <a for=request>destination</a> is "document", then return
3452+ "<code> lax-or-less</code> ".
3453+
3454+ <li><p> If <var> request</var> 's <a for=request>client</a>' s
3455+ <a for="environment settings object">has cross-site ancestor</a> is true, then return
3456+ "<code> unset-or-less</code> ".
3457+
3458+ <li><p> If <var> request</var> 's <a for=request>redirect-taint</a> is "<code> cross-site</code> ", then
3459+ return "<code> unset-or-less</code> ".
3460+
3461+ <li><p> Return "<code> strict-or-less</code> ".
3462+ </ol>
3463+ </div>
3464+
3465+
33183466<h3 id=origin-header>`<code>Origin</code>` header</h3>
33193467
33203468<p> The `<dfn export http-header id=http-origin><code>Origin</code></dfn> `
@@ -4729,8 +4877,8 @@ steps:
47294877 <!-- If you are ever tempted to move this around, carefully consider responses from about URLs,
47304878 blob URLs, service workers, HTTP cache, HTTP network, etc. -->
47314879
4732- < li > < p > If < var > request </ var > has a < a for =request > redirect-tainted origin </ a > , then set
4733- < var > internalResponse </ var > 's < a for =response > has-cross-origin-redirects </ a > to true .
4880+ <li><p> Set <var> internalResponse </var> 's <a for=response >redirect taint </a> to <var>request</var>' s
4881+ <a for=request>redirect-taint </a> .
47344882
47354883 <li><p> If <var> request</var> 's <a for=request>timing allow failed flag</a> is unset, then set
47364884 <var> internalResponse</var> 's <a for=response>timing allow passed flag</a> .
@@ -4883,7 +5031,7 @@ steps:
48835031 <li>
48845032 <p> If <var> fetchParams</var> 's <a for="fetch params">request</a>' s <a for=request>mode</a> is
48855033 not "<code> navigate</code> " or <var> response</var> 's
4886- < a for =response > has-cross-origin-redirects </ a > is false :
5034+ <a for=response>redirect taint </a> is " <code> same-origin </code> " :
48875035
48885036 <ol>
48895037 <li><p> Set <var> responseStatus</var> to <var> response</var> 's <a for=response>status</a> .
@@ -5766,21 +5914,7 @@ run these steps:
57665914 <p> If <var> includeCredentials</var> is true, then:
57675915
57685916 <ol>
5769- < li >
5770- < p > If the user agent is not configured to block cookies for < var > httpRequest</ var > (see
5771- < a href =https://httpwg.org/specs/rfc6265.html#privacy-considerations > section 7</ a > of
5772- [[!COOKIES]]), then:
5773-
5774- < ol >
5775- < li > < p > Let < var > cookies</ var > be the result of running the "cookie-string" algorithm (see
5776- < a href =https://httpwg.org/specs/rfc6265.html#cookie > section 5.4</ a > of
5777- [[!COOKIES]]) with the user agent's cookie store and < var > httpRequest</ var > 's
5778- < a for =request > current URL</ a > .
5779-
5780- < li > If < var > cookies</ var > is not the empty string, then < a for ="header list "> append</ a >
5781- (`< code > Cookie</ code > `, < var > cookies</ var > ) to < var > httpRequest</ var > 's
5782- < a for =request > header list</ a > .
5783- </ ol >
5917+ <li><p> <a>Append a request `<code>Cookie</code>` header</a> for <var> httpRequest</var> .
57845918
57855919 <li>
57865920 <p> If <var> httpRequest</var> 's <a for=request>header list</a>
@@ -6343,14 +6477,9 @@ optional boolean <var>forceNewConnection</var> (default false), run these steps:
63436477 <li><p> Set <var> response</var> 's <a for=response>body</a> to a new <a for=/>body</a> whose
63446478 <a for=body>stream</a> is <var> stream</var> .
63456479
6346- < li > < p tracking-vector > If < var > includeCredentials</ var > is true and the user agent is not
6347- configured to block cookies for < var > request</ var > (see
6348- < a href =https://httpwg.org/specs/rfc6265.html#privacy-considerations > section 7</ a > of
6349- [[!COOKIES]]), then run the "set-cookie-string" parsing algorithm (see
6350- < a href =https://httpwg.org/specs/rfc6265.html#set-cookie > section 5.2</ a > of [[!COOKIES]]) on the
6351- < a for =header > value</ a > of each < a for =/ > header</ a > whose < a for =header > name</ a > is a
6352- < a > byte-case-insensitive</ a > match for `< code > Set-Cookie</ code > ` in < var > response</ var > 's
6353- < a for =response > header list</ a > , if any, and < var > request</ var > 's < a for =request > current URL</ a > .
6480+ <li><p tracking-vector> If <var> includeCredentials</var> is true, then the user agent should
6481+ <a>parse and store response `<code>Set-Cookie</code>` headers</a> given <var> request</var> and
6482+ <var> response</var> .
63546483
63556484 <li>
63566485 <p> Run these steps <a>in parallel</a> :
@@ -9156,6 +9285,7 @@ Axel Rauschmayer,
91569285Ben Kelly,
91579286Benjamin Gruenbaum,
91589287Benjamin Hawkes-Lewis,
9288+ Benjamin VanderSloot,
91599289Bert Bos,
91609290Björn Höhrmann,
91619291Boris Zbarsky,
0 commit comments