From 8938b6980c3282f6e3589e083404673d61228947 Mon Sep 17 00:00:00 2001 From: Chris Mills Date: Mon, 1 Sep 2025 10:14:27 +0100 Subject: [PATCH 1/4] Document __Http- and __Host-Http- cookie prefixes --- files/en-us/web/api/document/cookie/index.md | 11 ++++---- files/en-us/web/http/guides/cookies/index.md | 16 ++++++----- .../reference/headers/set-cookie/index.md | 27 +++++++++++++------ 3 files changed, 34 insertions(+), 20 deletions(-) diff --git a/files/en-us/web/api/document/cookie/index.md b/files/en-us/web/api/document/cookie/index.md index 924b93465450c95..aee1da7be496e34 100644 --- a/files/en-us/web/api/document/cookie/index.md +++ b/files/en-us/web/api/document/cookie/index.md @@ -54,11 +54,10 @@ You can also assign to this property a string of the form `"key=value"`, specify - The cookie value string can use {{jsxref("Global_Objects/encodeURIComponent", "encodeURIComponent()")}} to ensure that the string does not contain any commas, semicolons, or whitespace (which are disallowed in cookie values). - Some user agent implementations support the following cookie prefixes: - - `__Secure-` Signals to the browser that it should only include the cookie in requests transmitted over a secure channel. - - `__Host-` Signals to the browser that in addition to the restriction to only use the cookie from a secure origin, the scope of the cookie is limited to a path attribute passed down by the server. - If the server omits the path attribute the "directory" of the request URI is used. - It also signals that the domain attribute must not be present, which prevents the cookie from being sent to other domains. - For Chrome the path attribute must always be the origin. + - **`__Secure-`**: Cookies with names starting with `__Secure-` (dash is part of the prefix) must be set with the `Secure` attribute by a secure page (HTTPS). + - **`__Host-`**: Cookies with names starting with `__Host-` must be set with the `Secure` attribute by a secure page (HTTPS) and in addition must be sent only to the host subdomain or domain that set them, and not to any other host. They must not have a `Domain` attribute specified, and the `Path` attribute must be set to `/` (for Chrome, the path attribute must always be the origin.). + - **`__Http-`**: Cookies with names starting with `__Http-` must be set with the `Secure` flag by a secure page (HTTPS) and in addition must have the `HttpOnly` attribute set to prove that they were set via the `Set-Cookie` header (they can't be set or modified via JavaScript features such as `Document.cookie` or the [Cookie Store API](/en-US/docs/Web/API/Cookie_Store_API)). + - **`__Host-Http-`**: Cookies with names starting with `__Host-Http-` must be set with the `Secure` flag by a secure page (HTTPS) and in addition must have the `HttpOnly` attribute set to prove that they were set via the `Set-Cookie` header and must be sent only to the host subdomain or domain that set them, and not to any other host. They must not have a `Domain` attribute specified, and the `Path` attribute must be set to `/`. This combination yields a cookie that is as close as a cookie can be to treating the origin as a security boundary while at the same time ensuring developers and server operators know that its scope is limited to HTTP requests. > [!NOTE] > The dash is considered part of the prefix. @@ -67,7 +66,7 @@ You can also assign to this property a string of the form `"key=value"`, specify > These flags are only settable with the `secure` attribute. > [!NOTE] -> As you can see from the code above, `document.cookie` is an [accessor property](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty#description) with native _setter_ and _getter_ functions, and consequently is _not_ a [data property](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty#description) with a value: what you write is not the same as what you read, everything is always mediated by the JavaScript interpreter. +> The `document.cookie` property is an [accessor property](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty#description) with native _setter_ and _getter_ functions, and consequently is _not_ a [data property](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty#description) with a value: what you write is not the same as what you read, everything is always mediated by the JavaScript interpreter. ## Examples diff --git a/files/en-us/web/http/guides/cookies/index.md b/files/en-us/web/http/guides/cookies/index.md index 2927b94fac7004b..b33a3114f5ab7da 100644 --- a/files/en-us/web/http/guides/cookies/index.md +++ b/files/en-us/web/http/guides/cookies/index.md @@ -113,7 +113,7 @@ document.cookie = "yummy_cookie=chocolate"; document.cookie = "tasty_cookie=strawberry"; ``` -You can also access existing cookies and set new values for them, provided the [`HttpOnly`](/en-US/docs/Web/HTTP/Reference/Headers/Set-Cookie#httponly) attribute isn't set on them (i.e., in the `Set-Cookie` header that created it): +You can also access existing cookies and set new values for them: ```js console.log(document.cookie); @@ -125,7 +125,9 @@ console.log(document.cookie); // logs "tasty_cookie=strawberry; yummy_cookie=blueberry" ``` -Note that, for security purposes, you can't change cookie values by sending an updated `Cookie` header directly when initiating a request, i.e., via {{domxref("Window/fetch", "fetch()")}} or {{domxref("XMLHttpRequest")}}. Note that there are also good reasons why you shouldn't allow JavaScript to modify cookies — i.e., set `HttpOnly` during creation. See the [Security](#security) section for more details. +For security purposes, you can't change cookie values by sending an updated `Cookie` header directly when initiating a request, for example, via {{domxref("Window/fetch", "fetch()")}} or {{domxref("XMLHttpRequest")}}. + +There are good reasons why you shouldn't allow JavaScript to modify cookies at all. You can prevent JavaScript from accessing a cookie by specifying the [`HttpOnly`](/en-US/docs/Web/HTTP/Reference/Headers/Set-Cookie#httponly) attribute during its creation. See the [Security](#security) section for more details. ## Security @@ -219,12 +221,14 @@ Because of the design of the cookie mechanism, a server can't confirm that a coo An application on a subdomain can set a cookie with the `Domain` attribute, which gives access to that cookie on all other subdomains. This mechanism can be abused in a [session fixation](https://owasp.org/www-community/attacks/Session_fixation) attack. -As a [defense-in-depth measure](), however, you can use _cookie prefixes_ to assert specific facts about the cookie. Two prefixes are available: +As a [defense-in-depth measure](), you can use _cookie prefixes_ to assert specific facts about the cookie. Four prefixes are available: -- `__Host-`: If a cookie name has this prefix, it's accepted in a {{HTTPHeader("Set-Cookie")}} header only if it's also marked with the `Secure` attribute, was sent from a secure origin, does _not_ include a `Domain` attribute, and has the `Path` attribute set to `/`. In other words, the cookie is _domain-locked_. -- `__Secure-`: If a cookie name has this prefix, it's accepted in a {{HTTPHeader("Set-Cookie")}} header only if it's marked with the `Secure` attribute and was sent from a secure origin. This is weaker than the `__Host-` prefix. +- **`__Secure-`**: Cookies with names starting with `__Secure-` (dash is part of the prefix) must be set with the `Secure` attribute by a secure page (HTTPS). +- **`__Host-`**: Cookies with names starting with `__Host-` must be set with the `Secure` attribute by a secure page (HTTPS) and in addition must be sent only to the host subdomain or domain that set them, and not to any other host. They must not have a `Domain` attribute specified, and the `Path` attribute must be set to `/`. +- **`__Http-`**: Cookies with names starting with `__Http-` must be set with the `Secure` flag by a secure page (HTTPS) and in addition must have the `HttpOnly` attribute set to prove that they were set via the `Set-Cookie` header (they can't be set or modified via JavaScript features such as {{domxref("Document.cookie")}} or the [Cookie Store API](/en-US/docs/Web/API/Cookie_Store_API)). +- **`__Host-Http-`**: Cookies with names starting with `__Host-Http-` must be set with the `Secure` flag by a secure page (HTTPS) and in addition must have the `HttpOnly` attribute set to prove that they were set via the `Set-Cookie` header and must be sent only to the host subdomain or domain that set them, and not to any other host. They must not have a `Domain` attribute specified, and the `Path` attribute must be set to `/`. This combination yields a cookie that is as close as a cookie can be to treating the origin as a security boundary while at the same time ensuring developers and server operators know that its scope is limited to HTTP requests. -The browser will reject cookies with these prefixes that don't comply with their restrictions. This ensures that subdomain-created cookies with prefixes are either confined to a subdomain or ignored completely. As the application server only checks for a specific cookie name when determining if the user is authenticated or a CSRF token is correct, this effectively acts as a defense measure against [session fixation](https://owasp.org/www-community/attacks/Session_fixation). +The browser will reject cookies with these prefixes that don't comply with their restrictions. As the application server only checks for a specific cookie name when determining if the user is authenticated or a CSRF token is correct, this effectively acts as a defense measure against [session fixation](https://owasp.org/www-community/attacks/Session_fixation). > [!NOTE] > On the server, the web application _must_ check for the full cookie name including the prefix. User agents _do not_ strip the prefix from the cookie before sending it in a request's {{HTTPHeader("Cookie")}} header. diff --git a/files/en-us/web/http/reference/headers/set-cookie/index.md b/files/en-us/web/http/reference/headers/set-cookie/index.md index d31e5146054d76c..9944cf83a56bcc7 100644 --- a/files/en-us/web/http/reference/headers/set-cookie/index.md +++ b/files/en-us/web/http/reference/headers/set-cookie/index.md @@ -60,7 +60,7 @@ Set-Cookie: =; Domain=; Secure; HttpOnl - : Defines the cookie name and its value. A cookie definition begins with a name-value pair. - A `` can contain any US-ASCII characters except for: control characters ({{Glossary("ASCII")}} characters 0 up to 31 and ASCII character 127) or separator characters (space, tab and the characters: `( ) < > @ , ; : \ " / [ ] ? = { }`) + A `` can contain any US-ASCII characters except for control characters ({{Glossary("ASCII")}} characters 0 up to 31 and ASCII character 127) or separator characters (space, tab and the characters: `( ) < > @ , ; : \ " / [ ] ? = { }`) A `` can optionally be wrapped in double quotes and include any US-ASCII character excluding control characters (ASCII characters 0 up to 31 and ASCII character 127), {{glossary("Whitespace")}}, double quotes, commas, semicolons, and backslashes. @@ -69,12 +69,17 @@ Set-Cookie: =; Domain=; Secure; HttpOnl The percent-encoding does help to satisfy the requirements of the characters allowed for ``. > [!NOTE] - > Some `` have a specific semantic: + > Some cookie names have prefixes added that confer specific semantics: > - > **`__Secure-` prefix**: Cookies with names starting with `__Secure-` (dash is part of the prefix) must be set with the `secure` flag from a secure page (HTTPS). + > **`__Secure-` prefix**: Cookies with names starting with `__Secure-` (dash is part of the prefix) must be set with the `Secure` attribute by a secure page (HTTPS). > - > **`__Host-` prefix**: Cookies with names starting with `__Host-` are sent only to the host subdomain or domain that set them, and not to any other host. - > They must be set with the `secure` flag, must be from a secure page (HTTPS), must not have a domain specified, and the path must be `/`. + > **`__Host-` prefix**: Cookies with names starting with `__Host-` must be set with the `Secure` attribute by a secure page (HTTPS) and in addition must be sent only + > to the host subdomain or domain that set them, and not to any other host. They must not have a `Domain` attribute specified, and the `Path` attribute must be set to `/`. + > + > **`__Http-` prefix**: Cookies with names starting with `__Http-` must be set with the `Secure` flag by a secure page (HTTPS) and in addition must have the `HttpOnly` + > attribute set to prove that they were set via the `Set-Cookie` header (they can't be set or modified via JavaScript features such as {{domxref("Document.cookie")}} or the [Cookie Store API](/en-US/docs/Web/API/Cookie_Store_API)). + > + > **`__Host-Http-` prefix**: Cookies with names starting with `__Host-Http-` must be set with the `Secure` flag by a secure page (HTTPS) and in addition must have the `HttpOnly` attribute set to prove that they were set via the `Set-Cookie` header and must be sent only to the host subdomain or domain that set them, and not to any other host. They must not have a `Domain` attribute specified, and the `Path` attribute must be set to `/`. This combination yields a cookie that is as close as a cookie can be to treating the origin as a security boundary while at the same time ensuring developers and server operators know that its scope is limited to HTTP requests. - `Domain=` {{optional_inline}} - : Defines the host to which the cookie will be sent. @@ -205,9 +210,11 @@ Set-Cookie: sessionId=e8bb43229de9; Domain=foo.example.com ### Cookie prefixes -Cookie names prefixed with `__Secure-` or `__Host-` can be used only if they are set with the `secure` attribute from a secure (HTTPS) origin. +Cookie names prefixed with `__Secure-` or `__Host-` can be used only if they are set with the `Secure` attribute from a secure (HTTPS) origin. -In addition, cookies with the `__Host-` prefix must have a path of `/` (meaning any path at the host) and must not have a `Domain` attribute. +Cookie names prefixed with `__Http-` or `__Host-Http-` can be used only if they are set with the `Secure` attribute from a secure (HTTPS) origin and in addition must have the `HttpOnly` attribute set to prove that they were set via the `Set-Cookie` header and not on the client-side via JavaScript. + +In addition, cookies with the `__Host-` or `__Host-Http-` prefix must have a path of `/` (meaning any path at the host) and must not have a `Domain` attribute. > [!WARNING] > For clients that don't implement cookie prefixes, you cannot count on these additional assurances, and prefixed cookies will always be accepted. @@ -225,6 +232,10 @@ Set-Cookie: __Host-id=1; Secure // Rejected due to setting a Domain Set-Cookie: __Host-id=1; Secure; Path=/; Domain=example.com + +// Only settable via Set-Cookie +Set-Cookie: __Http-ID=123; Secure; Domain=example.com +Set-Cookie: __Host-Http-ID=123; Secure; Path=/ ``` ### Partitioned cookie @@ -234,7 +245,7 @@ Set-Cookie: __Host-example=34d8g; SameSite=None; Secure; Path=/; Partitioned; ``` > [!NOTE] -> Partitioned cookies must be set with `Secure`. In addition, it is recommended to use the `__Host` prefix when setting partitioned cookies to make them bound to the hostname and not the registrable domain. +> Partitioned cookies must be set with `Secure`. In addition, it is recommended to use a `__Host` or `__Host-Http-` prefix when setting partitioned cookies to make them bound to the hostname and not the registrable domain. ## Specifications From 669b7cca4a808e7c500946b4c19cd0077c748ba8 Mon Sep 17 00:00:00 2001 From: Chris Mills Date: Mon, 1 Sep 2025 11:42:09 +0100 Subject: [PATCH 2/4] Fixes for yoavweiss review comments --- files/en-us/web/api/document/cookie/index.md | 8 +++---- files/en-us/web/http/guides/cookies/index.md | 8 +++---- .../reference/headers/set-cookie/index.md | 22 +++++++++---------- 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/files/en-us/web/api/document/cookie/index.md b/files/en-us/web/api/document/cookie/index.md index aee1da7be496e34..a96b4c047bcdfa1 100644 --- a/files/en-us/web/api/document/cookie/index.md +++ b/files/en-us/web/api/document/cookie/index.md @@ -53,11 +53,11 @@ You can also assign to this property a string of the form `"key=value"`, specify - `;secure`: Specifies that the cookie should only be transmitted over a secure protocol. - The cookie value string can use {{jsxref("Global_Objects/encodeURIComponent", "encodeURIComponent()")}} to ensure that the string does not contain any commas, semicolons, or whitespace (which are disallowed in cookie values). -- Some user agent implementations support the following cookie prefixes: - - **`__Secure-`**: Cookies with names starting with `__Secure-` (dash is part of the prefix) must be set with the `Secure` attribute by a secure page (HTTPS). - - **`__Host-`**: Cookies with names starting with `__Host-` must be set with the `Secure` attribute by a secure page (HTTPS) and in addition must be sent only to the host subdomain or domain that set them, and not to any other host. They must not have a `Domain` attribute specified, and the `Path` attribute must be set to `/` (for Chrome, the path attribute must always be the origin.). +- The cookie name can have a semantically meaningful prefix that imposes restrictions on the cookie's attributes in supporting user-agents. All cookie prefixes start with a double-underscore (`__`) and end in a dash (`-`). The following prefixes are defined: + - **`__Secure-`**: Cookies with names starting with `__Secure-` must be set with the `Secure` attribute by a secure page (HTTPS). + - **`__Host-`**: Cookies with names starting with `__Host-` must be set with the `Secure` attribute by a secure page (HTTPS). In addition, they must not have a `Domain` attribute specified, and the `Path` attribute must be set to `/`. This guarantees that such cookies are only sent to the host that set them, and not to any other host on the domain. It also guarantees that they are set host-wide and cannot be overridden on any path on that host. - **`__Http-`**: Cookies with names starting with `__Http-` must be set with the `Secure` flag by a secure page (HTTPS) and in addition must have the `HttpOnly` attribute set to prove that they were set via the `Set-Cookie` header (they can't be set or modified via JavaScript features such as `Document.cookie` or the [Cookie Store API](/en-US/docs/Web/API/Cookie_Store_API)). - - **`__Host-Http-`**: Cookies with names starting with `__Host-Http-` must be set with the `Secure` flag by a secure page (HTTPS) and in addition must have the `HttpOnly` attribute set to prove that they were set via the `Set-Cookie` header and must be sent only to the host subdomain or domain that set them, and not to any other host. They must not have a `Domain` attribute specified, and the `Path` attribute must be set to `/`. This combination yields a cookie that is as close as a cookie can be to treating the origin as a security boundary while at the same time ensuring developers and server operators know that its scope is limited to HTTP requests. + - **`__Host-Http-`**: Cookies with names starting with `__Host-Http-` must be set with the `Secure` flag by a secure page (HTTPS) and must have the `HttpOnly` attribute set to prove that they were set via the `Set-Cookie` header. In addition, they also have the same restrictions as `__Host-`-prefixed cookies. This combination yields a cookie that is as close as can be to treating the origin as a security boundary while at the same time ensuring developers and server operators know that its scope is limited to HTTP requests. > [!NOTE] > The dash is considered part of the prefix. diff --git a/files/en-us/web/http/guides/cookies/index.md b/files/en-us/web/http/guides/cookies/index.md index b33a3114f5ab7da..1c5da272c982ca4 100644 --- a/files/en-us/web/http/guides/cookies/index.md +++ b/files/en-us/web/http/guides/cookies/index.md @@ -221,12 +221,12 @@ Because of the design of the cookie mechanism, a server can't confirm that a coo An application on a subdomain can set a cookie with the `Domain` attribute, which gives access to that cookie on all other subdomains. This mechanism can be abused in a [session fixation](https://owasp.org/www-community/attacks/Session_fixation) attack. -As a [defense-in-depth measure](), you can use _cookie prefixes_ to assert specific facts about the cookie. Four prefixes are available: +As a [defense-in-depth measure](), you can use _cookie prefixes_ to assert specific facts about the cookie. All cookie prefixes start with a double-underscore (`__`) and end in a dash (`-`). Four prefixes are available: -- **`__Secure-`**: Cookies with names starting with `__Secure-` (dash is part of the prefix) must be set with the `Secure` attribute by a secure page (HTTPS). -- **`__Host-`**: Cookies with names starting with `__Host-` must be set with the `Secure` attribute by a secure page (HTTPS) and in addition must be sent only to the host subdomain or domain that set them, and not to any other host. They must not have a `Domain` attribute specified, and the `Path` attribute must be set to `/`. +- **`__Secure-`**: Cookies with names starting with `__Secure-` must be set with the `Secure` attribute by a secure page (HTTPS). +- **`__Host-`**: Cookies with names starting with `__Host-` must be set with the `Secure` attribute by a secure page (HTTPS). In addition, they must not have a `Domain` attribute specified, and the `Path` attribute must be set to `/`. This guarantees that such cookies are only sent to the host that set them, and not to any other host on the domain. It also guarantees that they are set host-wide and cannot be overridden on any path on that host. - **`__Http-`**: Cookies with names starting with `__Http-` must be set with the `Secure` flag by a secure page (HTTPS) and in addition must have the `HttpOnly` attribute set to prove that they were set via the `Set-Cookie` header (they can't be set or modified via JavaScript features such as {{domxref("Document.cookie")}} or the [Cookie Store API](/en-US/docs/Web/API/Cookie_Store_API)). -- **`__Host-Http-`**: Cookies with names starting with `__Host-Http-` must be set with the `Secure` flag by a secure page (HTTPS) and in addition must have the `HttpOnly` attribute set to prove that they were set via the `Set-Cookie` header and must be sent only to the host subdomain or domain that set them, and not to any other host. They must not have a `Domain` attribute specified, and the `Path` attribute must be set to `/`. This combination yields a cookie that is as close as a cookie can be to treating the origin as a security boundary while at the same time ensuring developers and server operators know that its scope is limited to HTTP requests. +- **`__Host-Http-`**: Cookies with names starting with `__Host-Http-` must be set with the `Secure` flag by a secure page (HTTPS) and must have the `HttpOnly` attribute set to prove that they were set via the `Set-Cookie` header. In addition, they also have the same restrictions as `__Host-`-prefixed cookies. This combination yields a cookie that is as close as can be to treating the origin as a security boundary while at the same time ensuring developers and server operators know that its scope is limited to HTTP requests. The browser will reject cookies with these prefixes that don't comply with their restrictions. As the application server only checks for a specific cookie name when determining if the user is authenticated or a CSRF token is correct, this effectively acts as a defense measure against [session fixation](https://owasp.org/www-community/attacks/Session_fixation). diff --git a/files/en-us/web/http/reference/headers/set-cookie/index.md b/files/en-us/web/http/reference/headers/set-cookie/index.md index 9944cf83a56bcc7..3a1444dc1f7ff0e 100644 --- a/files/en-us/web/http/reference/headers/set-cookie/index.md +++ b/files/en-us/web/http/reference/headers/set-cookie/index.md @@ -68,18 +68,16 @@ Set-Cookie: =; Domain=; Secure; HttpOnl However, this is not required by the RFC specification. The percent-encoding does help to satisfy the requirements of the characters allowed for ``. - > [!NOTE] - > Some cookie names have prefixes added that confer specific semantics: - > - > **`__Secure-` prefix**: Cookies with names starting with `__Secure-` (dash is part of the prefix) must be set with the `Secure` attribute by a secure page (HTTPS). - > - > **`__Host-` prefix**: Cookies with names starting with `__Host-` must be set with the `Secure` attribute by a secure page (HTTPS) and in addition must be sent only - > to the host subdomain or domain that set them, and not to any other host. They must not have a `Domain` attribute specified, and the `Path` attribute must be set to `/`. - > - > **`__Http-` prefix**: Cookies with names starting with `__Http-` must be set with the `Secure` flag by a secure page (HTTPS) and in addition must have the `HttpOnly` - > attribute set to prove that they were set via the `Set-Cookie` header (they can't be set or modified via JavaScript features such as {{domxref("Document.cookie")}} or the [Cookie Store API](/en-US/docs/Web/API/Cookie_Store_API)). - > - > **`__Host-Http-` prefix**: Cookies with names starting with `__Host-Http-` must be set with the `Secure` flag by a secure page (HTTPS) and in addition must have the `HttpOnly` attribute set to prove that they were set via the `Set-Cookie` header and must be sent only to the host subdomain or domain that set them, and not to any other host. They must not have a `Domain` attribute specified, and the `Path` attribute must be set to `/`. This combination yields a cookie that is as close as a cookie can be to treating the origin as a security boundary while at the same time ensuring developers and server operators know that its scope is limited to HTTP requests. + > [!NOTE] + > Some cookie names have prefixes added that confer specific semantics. All cookie prefixes start with a double-underscore (`__`) and end in a dash (`-`). The following prefixes are defined: + > + > **`__Secure-`**: Cookies with names starting with `__Secure-` must be set with the `Secure` attribute by a secure page (HTTPS). + > + > **`__Host-`**: Cookies with names starting with `__Host-` must be set with the `Secure` attribute by a secure page (HTTPS). In addition, they must not have a `Domain` attribute specified, and the `Path` attribute must be set to `/`. This guarantees that such cookies are only sent to the host that set them, and not to any other host on the domain. It also guarantees that they are set host-wide and cannot be overridden on any path on that host. + > + > **`__Http-`**: Cookies with names starting with `__Http-` must be set with the `Secure` flag by a secure page (HTTPS) and in addition must have the `HttpOnly` attribute set to prove that they were set via the `Set-Cookie` header (they can't be set or modified via JavaScript features such as `Document.cookie` or the [Cookie Store API](/en-US/docs/Web/API/Cookie_Store_API)). + > + > **`__Host-Http-`**: Cookies with names starting with `__Host-Http-` must be set with the `Secure` flag by a secure page (HTTPS) and must have the `HttpOnly` attribute set to prove that they were set via the `Set-Cookie` header. In addition, they also have the same restrictions as `__Host-`-prefixed cookies. This combination yields a cookie that is as close as can be to treating the origin as a security boundary while at the same time ensuring developers and server operators know that its scope is limited to HTTP requests. - `Domain=` {{optional_inline}} - : Defines the host to which the cookie will be sent. From e3b4ee4a03eab7efaa3def7eb143e3e88e648281 Mon Sep 17 00:00:00 2001 From: Chris Mills Date: Mon, 1 Sep 2025 12:27:34 +0100 Subject: [PATCH 3/4] Add security boundary line to __Host- description --- files/en-us/web/api/document/cookie/index.md | 2 +- files/en-us/web/http/guides/cookies/index.md | 2 +- files/en-us/web/http/reference/headers/set-cookie/index.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/files/en-us/web/api/document/cookie/index.md b/files/en-us/web/api/document/cookie/index.md index a96b4c047bcdfa1..c5adb2fb3548a99 100644 --- a/files/en-us/web/api/document/cookie/index.md +++ b/files/en-us/web/api/document/cookie/index.md @@ -55,7 +55,7 @@ You can also assign to this property a string of the form `"key=value"`, specify - The cookie value string can use {{jsxref("Global_Objects/encodeURIComponent", "encodeURIComponent()")}} to ensure that the string does not contain any commas, semicolons, or whitespace (which are disallowed in cookie values). - The cookie name can have a semantically meaningful prefix that imposes restrictions on the cookie's attributes in supporting user-agents. All cookie prefixes start with a double-underscore (`__`) and end in a dash (`-`). The following prefixes are defined: - **`__Secure-`**: Cookies with names starting with `__Secure-` must be set with the `Secure` attribute by a secure page (HTTPS). - - **`__Host-`**: Cookies with names starting with `__Host-` must be set with the `Secure` attribute by a secure page (HTTPS). In addition, they must not have a `Domain` attribute specified, and the `Path` attribute must be set to `/`. This guarantees that such cookies are only sent to the host that set them, and not to any other host on the domain. It also guarantees that they are set host-wide and cannot be overridden on any path on that host. + - **`__Host-`**: Cookies with names starting with `__Host-` must be set with the `Secure` attribute by a secure page (HTTPS). In addition, they must not have a `Domain` attribute specified, and the `Path` attribute must be set to `/`. This guarantees that such cookies are only sent to the host that set them, and not to any other host on the domain. It also guarantees that they are set host-wide and cannot be overridden on any path on that host. This combination yields a cookie that is as close as can be to treating the origin as a security boundary. - **`__Http-`**: Cookies with names starting with `__Http-` must be set with the `Secure` flag by a secure page (HTTPS) and in addition must have the `HttpOnly` attribute set to prove that they were set via the `Set-Cookie` header (they can't be set or modified via JavaScript features such as `Document.cookie` or the [Cookie Store API](/en-US/docs/Web/API/Cookie_Store_API)). - **`__Host-Http-`**: Cookies with names starting with `__Host-Http-` must be set with the `Secure` flag by a secure page (HTTPS) and must have the `HttpOnly` attribute set to prove that they were set via the `Set-Cookie` header. In addition, they also have the same restrictions as `__Host-`-prefixed cookies. This combination yields a cookie that is as close as can be to treating the origin as a security boundary while at the same time ensuring developers and server operators know that its scope is limited to HTTP requests. diff --git a/files/en-us/web/http/guides/cookies/index.md b/files/en-us/web/http/guides/cookies/index.md index 1c5da272c982ca4..3e9a95bb653af0a 100644 --- a/files/en-us/web/http/guides/cookies/index.md +++ b/files/en-us/web/http/guides/cookies/index.md @@ -224,7 +224,7 @@ An application on a subdomain can set a cookie with the `Domain` attribute, whic As a [defense-in-depth measure](), you can use _cookie prefixes_ to assert specific facts about the cookie. All cookie prefixes start with a double-underscore (`__`) and end in a dash (`-`). Four prefixes are available: - **`__Secure-`**: Cookies with names starting with `__Secure-` must be set with the `Secure` attribute by a secure page (HTTPS). -- **`__Host-`**: Cookies with names starting with `__Host-` must be set with the `Secure` attribute by a secure page (HTTPS). In addition, they must not have a `Domain` attribute specified, and the `Path` attribute must be set to `/`. This guarantees that such cookies are only sent to the host that set them, and not to any other host on the domain. It also guarantees that they are set host-wide and cannot be overridden on any path on that host. +- **`__Host-`**: Cookies with names starting with `__Host-` must be set with the `Secure` attribute by a secure page (HTTPS). In addition, they must not have a `Domain` attribute specified, and the `Path` attribute must be set to `/`. This guarantees that such cookies are only sent to the host that set them, and not to any other host on the domain. It also guarantees that they are set host-wide and cannot be overridden on any path on that host. This combination yields a cookie that is as close as can be to treating the origin as a security boundary. - **`__Http-`**: Cookies with names starting with `__Http-` must be set with the `Secure` flag by a secure page (HTTPS) and in addition must have the `HttpOnly` attribute set to prove that they were set via the `Set-Cookie` header (they can't be set or modified via JavaScript features such as {{domxref("Document.cookie")}} or the [Cookie Store API](/en-US/docs/Web/API/Cookie_Store_API)). - **`__Host-Http-`**: Cookies with names starting with `__Host-Http-` must be set with the `Secure` flag by a secure page (HTTPS) and must have the `HttpOnly` attribute set to prove that they were set via the `Set-Cookie` header. In addition, they also have the same restrictions as `__Host-`-prefixed cookies. This combination yields a cookie that is as close as can be to treating the origin as a security boundary while at the same time ensuring developers and server operators know that its scope is limited to HTTP requests. diff --git a/files/en-us/web/http/reference/headers/set-cookie/index.md b/files/en-us/web/http/reference/headers/set-cookie/index.md index 3a1444dc1f7ff0e..868d0a85bc9bdc8 100644 --- a/files/en-us/web/http/reference/headers/set-cookie/index.md +++ b/files/en-us/web/http/reference/headers/set-cookie/index.md @@ -73,7 +73,7 @@ Set-Cookie: =; Domain=; Secure; HttpOnl > > **`__Secure-`**: Cookies with names starting with `__Secure-` must be set with the `Secure` attribute by a secure page (HTTPS). > - > **`__Host-`**: Cookies with names starting with `__Host-` must be set with the `Secure` attribute by a secure page (HTTPS). In addition, they must not have a `Domain` attribute specified, and the `Path` attribute must be set to `/`. This guarantees that such cookies are only sent to the host that set them, and not to any other host on the domain. It also guarantees that they are set host-wide and cannot be overridden on any path on that host. + > **`__Host-`**: Cookies with names starting with `__Host-` must be set with the `Secure` attribute by a secure page (HTTPS). In addition, they must not have a `Domain` attribute specified, and the `Path` attribute must be set to `/`. This guarantees that such cookies are only sent to the host that set them, and not to any other host on the domain. It also guarantees that they are set host-wide and cannot be overridden on any path on that host. This combination yields a cookie that is as close as can be to treating the origin as a security boundary. > > **`__Http-`**: Cookies with names starting with `__Http-` must be set with the `Secure` flag by a secure page (HTTPS) and in addition must have the `HttpOnly` attribute set to prove that they were set via the `Set-Cookie` header (they can't be set or modified via JavaScript features such as `Document.cookie` or the [Cookie Store API](/en-US/docs/Web/API/Cookie_Store_API)). > From 9d6f7a7a2e57fe4caf4a0d1394a22feb28a03809 Mon Sep 17 00:00:00 2001 From: Chris Mills Date: Mon, 1 Sep 2025 16:23:07 +0100 Subject: [PATCH 4/4] Fixes for bsmth review comments --- files/en-us/web/api/document/cookie/index.md | 2 +- files/en-us/web/http/guides/cookies/index.md | 2 +- .../reference/headers/set-cookie/index.md | 33 +++++++++---------- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/files/en-us/web/api/document/cookie/index.md b/files/en-us/web/api/document/cookie/index.md index c5adb2fb3548a99..43b9422d1f97c17 100644 --- a/files/en-us/web/api/document/cookie/index.md +++ b/files/en-us/web/api/document/cookie/index.md @@ -53,7 +53,7 @@ You can also assign to this property a string of the form `"key=value"`, specify - `;secure`: Specifies that the cookie should only be transmitted over a secure protocol. - The cookie value string can use {{jsxref("Global_Objects/encodeURIComponent", "encodeURIComponent()")}} to ensure that the string does not contain any commas, semicolons, or whitespace (which are disallowed in cookie values). -- The cookie name can have a semantically meaningful prefix that imposes restrictions on the cookie's attributes in supporting user-agents. All cookie prefixes start with a double-underscore (`__`) and end in a dash (`-`). The following prefixes are defined: +- The cookie name can have a prefix that imposes specific restrictions on the cookie's attributes in supporting user-agents. All cookie prefixes start with a double-underscore (`__`) and end in a dash (`-`). The following prefixes are defined: - **`__Secure-`**: Cookies with names starting with `__Secure-` must be set with the `Secure` attribute by a secure page (HTTPS). - **`__Host-`**: Cookies with names starting with `__Host-` must be set with the `Secure` attribute by a secure page (HTTPS). In addition, they must not have a `Domain` attribute specified, and the `Path` attribute must be set to `/`. This guarantees that such cookies are only sent to the host that set them, and not to any other host on the domain. It also guarantees that they are set host-wide and cannot be overridden on any path on that host. This combination yields a cookie that is as close as can be to treating the origin as a security boundary. - **`__Http-`**: Cookies with names starting with `__Http-` must be set with the `Secure` flag by a secure page (HTTPS) and in addition must have the `HttpOnly` attribute set to prove that they were set via the `Set-Cookie` header (they can't be set or modified via JavaScript features such as `Document.cookie` or the [Cookie Store API](/en-US/docs/Web/API/Cookie_Store_API)). diff --git a/files/en-us/web/http/guides/cookies/index.md b/files/en-us/web/http/guides/cookies/index.md index 3e9a95bb653af0a..d33adea7eb3f391 100644 --- a/files/en-us/web/http/guides/cookies/index.md +++ b/files/en-us/web/http/guides/cookies/index.md @@ -221,7 +221,7 @@ Because of the design of the cookie mechanism, a server can't confirm that a coo An application on a subdomain can set a cookie with the `Domain` attribute, which gives access to that cookie on all other subdomains. This mechanism can be abused in a [session fixation](https://owasp.org/www-community/attacks/Session_fixation) attack. -As a [defense-in-depth measure](), you can use _cookie prefixes_ to assert specific facts about the cookie. All cookie prefixes start with a double-underscore (`__`) and end in a dash (`-`). Four prefixes are available: +As a [defense-in-depth measure](), you can use _cookie prefixes_ to impose specific restrictions on a cookie's attributes in supporting user-agents. All cookie prefixes start with a double-underscore (`__`) and end in a dash (`-`). Four prefixes are available: - **`__Secure-`**: Cookies with names starting with `__Secure-` must be set with the `Secure` attribute by a secure page (HTTPS). - **`__Host-`**: Cookies with names starting with `__Host-` must be set with the `Secure` attribute by a secure page (HTTPS). In addition, they must not have a `Domain` attribute specified, and the `Path` attribute must be set to `/`. This guarantees that such cookies are only sent to the host that set them, and not to any other host on the domain. It also guarantees that they are set host-wide and cannot be overridden on any path on that host. This combination yields a cookie that is as close as can be to treating the origin as a security boundary. diff --git a/files/en-us/web/http/reference/headers/set-cookie/index.md b/files/en-us/web/http/reference/headers/set-cookie/index.md index 868d0a85bc9bdc8..6f79a3813cc456a 100644 --- a/files/en-us/web/http/reference/headers/set-cookie/index.md +++ b/files/en-us/web/http/reference/headers/set-cookie/index.md @@ -64,20 +64,10 @@ Set-Cookie: =; Domain=; Secure; HttpOnl A `` can optionally be wrapped in double quotes and include any US-ASCII character excluding control characters (ASCII characters 0 up to 31 and ASCII character 127), {{glossary("Whitespace")}}, double quotes, commas, semicolons, and backslashes. - **Encoding**: Many implementations perform {{Glossary("Percent-encoding", "percent-encoding")}} on cookie values. - However, this is not required by the RFC specification. - The percent-encoding does help to satisfy the requirements of the characters allowed for ``. - - > [!NOTE] - > Some cookie names have prefixes added that confer specific semantics. All cookie prefixes start with a double-underscore (`__`) and end in a dash (`-`). The following prefixes are defined: - > - > **`__Secure-`**: Cookies with names starting with `__Secure-` must be set with the `Secure` attribute by a secure page (HTTPS). - > - > **`__Host-`**: Cookies with names starting with `__Host-` must be set with the `Secure` attribute by a secure page (HTTPS). In addition, they must not have a `Domain` attribute specified, and the `Path` attribute must be set to `/`. This guarantees that such cookies are only sent to the host that set them, and not to any other host on the domain. It also guarantees that they are set host-wide and cannot be overridden on any path on that host. This combination yields a cookie that is as close as can be to treating the origin as a security boundary. - > - > **`__Http-`**: Cookies with names starting with `__Http-` must be set with the `Secure` flag by a secure page (HTTPS) and in addition must have the `HttpOnly` attribute set to prove that they were set via the `Set-Cookie` header (they can't be set or modified via JavaScript features such as `Document.cookie` or the [Cookie Store API](/en-US/docs/Web/API/Cookie_Store_API)). - > - > **`__Host-Http-`**: Cookies with names starting with `__Host-Http-` must be set with the `Secure` flag by a secure page (HTTPS) and must have the `HttpOnly` attribute set to prove that they were set via the `Set-Cookie` header. In addition, they also have the same restrictions as `__Host-`-prefixed cookies. This combination yields a cookie that is as close as can be to treating the origin as a security boundary while at the same time ensuring developers and server operators know that its scope is limited to HTTP requests. + **Encoding**: Many implementations perform {{Glossary("Percent-encoding", "percent-encoding")}} on cookie values. However, this is not required by the RFC specification. The percent-encoding does help to satisfy the requirements of the characters allowed for ``. + + > [!NOTE] + > Some cookie names contain prefixes that impose specific restrictions on the cookie's attributes in supporting user-agents. See [Cookie prefixes](#cookie_prefixes) for more information. - `Domain=` {{optional_inline}} - : Defines the host to which the cookie will be sent. @@ -166,6 +156,18 @@ Set-Cookie: =; Domain=; Secure; HttpOnl > > Insecure sites (`http:`) cannot set cookies with the `Secure` attribute. The `https:` requirements are ignored when the `Secure` attribute is set by localhost. +## Cookie prefixes + +Some cookie names contain prefixes that impose specific restrictions on the cookie's attributes in supporting user-agents. All cookie prefixes start with a double-underscore (`__`) and end in a dash (`-`). The following prefixes are defined: + +- **`__Secure-`**: Cookies with names starting with `__Secure-` must be set with the `Secure` attribute by a secure page (HTTPS). +- **`__Host-`**: Cookies with names starting with `__Host-` must be set with the `Secure` attribute by a secure page (HTTPS). In addition, they must not have a `Domain` attribute specified, and the `Path` attribute must be set to `/`. This guarantees that such cookies are only sent to the host that set them, and not to any other host on the domain. It also guarantees that they are set host-wide and cannot be overridden on any path on that host. This combination yields a cookie that is as close as can be to treating the origin as a security boundary. +- **`__Http-`**: Cookies with names starting with `__Http-` must be set with the `Secure` flag by a secure page (HTTPS) and in addition must have the `HttpOnly` attribute set to prove that they were set via the `Set-Cookie` header (they can't be set or modified via JavaScript features such as `Document.cookie` or the [Cookie Store API](/en-US/docs/Web/API/Cookie_Store_API)). +- **`__Host-Http-`**: Cookies with names starting with `__Host-Http-` must be set with the `Secure` flag by a secure page (HTTPS) and must have the `HttpOnly` attribute set to prove that they were set via the `Set-Cookie` header. In addition, they also have the same restrictions as `__Host-`-prefixed cookies. This combination yields a cookie that is as close as can be to treating the origin as a security boundary while at the same time ensuring developers and server operators know that its scope is limited to HTTP requests. + +> [!WARNING] +> You cannot count on these additional assurances on browsers that don't support cookie prefixes; in such cases, prefixed cookies will always be accepted. + ## Examples ### Session cookie @@ -214,9 +216,6 @@ Cookie names prefixed with `__Http-` or `__Host-Http-` can be used only if they In addition, cookies with the `__Host-` or `__Host-Http-` prefix must have a path of `/` (meaning any path at the host) and must not have a `Domain` attribute. -> [!WARNING] -> For clients that don't implement cookie prefixes, you cannot count on these additional assurances, and prefixed cookies will always be accepted. - ```http // Both accepted when from a secure origin (HTTPS) Set-Cookie: __Secure-ID=123; Secure; Domain=example.com