From 5901f2e404c22050e80c6d5476365153572fb570 Mon Sep 17 00:00:00 2001 From: Giles Copp Date: Mon, 4 Dec 2023 10:47:38 -0500 Subject: [PATCH 01/14] Add support for 'partitioned' attribute in http.cookies --- Doc/library/http.cookies.rst | 11 +++++++++++ Lib/http/cookies.py | 21 +++++++++++---------- Lib/test/test_http_cookies.py | 8 ++++++++ 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/Doc/library/http.cookies.rst b/Doc/library/http.cookies.rst index a2c1eb00d8b33d..f99ee5acb5664c 100644 --- a/Doc/library/http.cookies.rst +++ b/Doc/library/http.cookies.rst @@ -140,6 +140,7 @@ Morsel Objects * ``version`` * ``httponly`` * ``samesite`` + * ``partitioned`` The attribute :attr:`httponly` specifies that the cookie is only transferred in HTTP requests, and is not accessible through JavaScript. This is intended @@ -149,6 +150,13 @@ Morsel Objects send the cookie along with cross-site requests. This helps to mitigate CSRF attacks. Valid values for this attribute are "Strict" and "Lax". + The attribute :attr:`partitioned` indicates to user agents that these + cross-site cookies should only be available in the same top-level context + that the cookie was first set in. Must also set ``Secure`` and ``Path=/``. + 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. + The keys are case-insensitive and their default value is ``''``. .. versionchanged:: 3.5 @@ -163,6 +171,9 @@ Morsel Objects .. versionchanged:: 3.8 Added support for the :attr:`samesite` attribute. + .. versionchanged:: 3.13 + Added support for the :attr:`partitioned` attribute. + .. attribute:: Morsel.value diff --git a/Lib/http/cookies.py b/Lib/http/cookies.py index 35ac2dc6ae280c..e71b3a07b860ef 100644 --- a/Lib/http/cookies.py +++ b/Lib/http/cookies.py @@ -273,18 +273,19 @@ class Morsel(dict): # variant on the left to the appropriate traditional # formatting on the right. _reserved = { - "expires" : "expires", - "path" : "Path", - "comment" : "Comment", - "domain" : "Domain", - "max-age" : "Max-Age", - "secure" : "Secure", - "httponly" : "HttpOnly", - "version" : "Version", - "samesite" : "SameSite", + "expires" : "expires", + "path" : "Path", + "comment" : "Comment", + "domain" : "Domain", + "max-age" : "Max-Age", + "secure" : "Secure", + "httponly" : "HttpOnly", + "version" : "Version", + "samesite" : "SameSite", + "partitioned" : "Partitioned", } - _flags = {'secure', 'httponly'} + _flags = {'secure', 'httponly', 'partitioned'} def __init__(self): # Set defaults diff --git a/Lib/test/test_http_cookies.py b/Lib/test/test_http_cookies.py index 925c8697f60de6..15ea4f02e58fff 100644 --- a/Lib/test/test_http_cookies.py +++ b/Lib/test/test_http_cookies.py @@ -121,6 +121,14 @@ def test_set_secure_httponly_attrs(self): self.assertEqual(C.output(), 'Set-Cookie: Customer="WILE_E_COYOTE"; HttpOnly; Secure') + def test_set_secure_httponly_attrs(self): + C = cookies.SimpleCookie('Customer="WILE_E_COYOTE"') + C['Customer']['secure'] = True + C['Customer']['httponly'] = True + C['Customer']['partitioned'] = True + self.assertEqual(C.output(), + 'Set-Cookie: Customer="WILE_E_COYOTE"; HttpOnly; Partitioned; Secure') + def test_samesite_attrs(self): samesite_values = ['Strict', 'Lax', 'strict', 'lax'] for val in samesite_values: From 9175076be430ac4c7ffaa2bfc23ddde1bf2eb994 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 15:53:26 +0000 Subject: [PATCH 02/14] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2023-12-04-15-53-25.gh-issue-112713.Zrhv77.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-12-04-15-53-25.gh-issue-112713.Zrhv77.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-12-04-15-53-25.gh-issue-112713.Zrhv77.rst b/Misc/NEWS.d/next/Core and Builtins/2023-12-04-15-53-25.gh-issue-112713.Zrhv77.rst new file mode 100644 index 00000000000000..d00a7f9446da1a --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-12-04-15-53-25.gh-issue-112713.Zrhv77.rst @@ -0,0 +1 @@ +Added support for the ``Partitioned`` cookie flag to the ``http.cookies`` module. From f20ba61b82271e941f7cf866d345bb22566ed8e7 Mon Sep 17 00:00:00 2001 From: Giles Copp Date: Mon, 4 Dec 2023 11:09:14 -0500 Subject: [PATCH 03/14] Fix invalid test name function --- Lib/test/test_http_cookies.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_http_cookies.py b/Lib/test/test_http_cookies.py index 15ea4f02e58fff..e39f3851c70019 100644 --- a/Lib/test/test_http_cookies.py +++ b/Lib/test/test_http_cookies.py @@ -121,7 +121,7 @@ def test_set_secure_httponly_attrs(self): self.assertEqual(C.output(), 'Set-Cookie: Customer="WILE_E_COYOTE"; HttpOnly; Secure') - def test_set_secure_httponly_attrs(self): + def test_set_secure_httponly_partitioned_attrs(self): C = cookies.SimpleCookie('Customer="WILE_E_COYOTE"') C['Customer']['secure'] = True C['Customer']['httponly'] = True From 80df6e761697377d4e5dcd280a18b810e09bcbc9 Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith [Google LLC]" Date: Tue, 13 Feb 2024 17:52:02 -0800 Subject: [PATCH 04/14] Wordsmith the docs and include a link to the spec. --- Doc/library/http.cookies.rst | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Doc/library/http.cookies.rst b/Doc/library/http.cookies.rst index 99ef22d26df276..05b43c438a07ab 100644 --- a/Doc/library/http.cookies.rst +++ b/Doc/library/http.cookies.rst @@ -153,11 +153,16 @@ Morsel Objects attacks. Valid values for this attribute are "Strict" and "Lax". The attribute :attr:`partitioned` indicates to user agents that these - cross-site cookies should only be available in the same top-level context - that the cookie was first set in. Must also set ``Secure`` and ``Path=/``. + cross-site cookies *should* only be available in the same top-level context + that the cookie was first set in. For this to be accepted by the user agent, + you **must** also set both ``Secure`` and ``Path=/``. 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. + registrable domain. Read + `CHIPS (Cookies Having Independent Partitioned State)`_ + for full details and examples. + + .. _CHIPS (Cookies Having Independent Partitioned State): https://github.com/privacycg/CHIPS/blob/main/README.md The keys are case-insensitive and their default value is ``''``. From 21cf60e47ff9a28f934377294e2536a3dced7bbc Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith [Google LLC]" Date: Tue, 13 Feb 2024 17:54:50 -0800 Subject: [PATCH 05/14] Style: Don't retain unusual hand spacing. --- Lib/http/cookies.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Lib/http/cookies.py b/Lib/http/cookies.py index e71b3a07b860ef..397b008bcc3f93 100644 --- a/Lib/http/cookies.py +++ b/Lib/http/cookies.py @@ -273,16 +273,16 @@ class Morsel(dict): # variant on the left to the appropriate traditional # formatting on the right. _reserved = { - "expires" : "expires", - "path" : "Path", - "comment" : "Comment", - "domain" : "Domain", - "max-age" : "Max-Age", - "secure" : "Secure", - "httponly" : "HttpOnly", - "version" : "Version", - "samesite" : "SameSite", - "partitioned" : "Partitioned", + "expires": "expires", + "path": "Path", + "comment": "Comment", + "domain": "Domain", + "max-age": "Max-Age", + "secure": "Secure", + "httponly": "HttpOnly", + "version": "Version", + "samesite": "SameSite", + "partitioned": "Partitioned", } _flags = {'secure', 'httponly', 'partitioned'} From b1f7cbd8504816534f4a49aa5819a1110961cebf Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith [Google LLC]" Date: Tue, 13 Feb 2024 18:01:44 -0800 Subject: [PATCH 06/14] News ReST improvements. --- .../2023-12-04-15-53-25.gh-issue-112713.Zrhv77.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-12-04-15-53-25.gh-issue-112713.Zrhv77.rst b/Misc/NEWS.d/next/Core and Builtins/2023-12-04-15-53-25.gh-issue-112713.Zrhv77.rst index d00a7f9446da1a..ee1f33f95647bd 100644 --- a/Misc/NEWS.d/next/Core and Builtins/2023-12-04-15-53-25.gh-issue-112713.Zrhv77.rst +++ b/Misc/NEWS.d/next/Core and Builtins/2023-12-04-15-53-25.gh-issue-112713.Zrhv77.rst @@ -1 +1 @@ -Added support for the ``Partitioned`` cookie flag to the ``http.cookies`` module. +Added support for the ``Partitioned`` cookie flag in :mod:`http.cookies`. From f6391d6f43e65e357b0095004c542f3aadaef06e Mon Sep 17 00:00:00 2001 From: Giles Copp Date: Mon, 4 Dec 2023 10:47:38 -0500 Subject: [PATCH 07/14] Add support for 'partitioned' attribute in http.cookies --- Doc/library/http.cookies.rst | 11 +++++++++++ Lib/http/cookies.py | 21 +++++++++++---------- Lib/test/test_http_cookies.py | 8 ++++++++ 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/Doc/library/http.cookies.rst b/Doc/library/http.cookies.rst index 4ce2e3c4f4cb42..ad489a8b3c35b3 100644 --- a/Doc/library/http.cookies.rst +++ b/Doc/library/http.cookies.rst @@ -142,6 +142,7 @@ Morsel Objects version httponly samesite + partitioned The attribute :attr:`httponly` specifies that the cookie is only transferred in HTTP requests, and is not accessible through JavaScript. This is intended @@ -151,6 +152,13 @@ Morsel Objects send the cookie along with cross-site requests. This helps to mitigate CSRF attacks. Valid values for this attribute are "Strict" and "Lax". + The attribute :attr:`partitioned` indicates to user agents that these + cross-site cookies should only be available in the same top-level context + that the cookie was first set in. Must also set ``Secure`` and ``Path=/``. + 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. + The keys are case-insensitive and their default value is ``''``. .. versionchanged:: 3.5 @@ -165,6 +173,9 @@ Morsel Objects .. versionchanged:: 3.8 Added support for the :attr:`samesite` attribute. + .. versionchanged:: 3.13 + Added support for the :attr:`partitioned` attribute. + .. attribute:: Morsel.value diff --git a/Lib/http/cookies.py b/Lib/http/cookies.py index 6b9ed24ad8ec78..617eb25daf03d8 100644 --- a/Lib/http/cookies.py +++ b/Lib/http/cookies.py @@ -255,18 +255,19 @@ class Morsel(dict): # variant on the left to the appropriate traditional # formatting on the right. _reserved = { - "expires" : "expires", - "path" : "Path", - "comment" : "Comment", - "domain" : "Domain", - "max-age" : "Max-Age", - "secure" : "Secure", - "httponly" : "HttpOnly", - "version" : "Version", - "samesite" : "SameSite", + "expires" : "expires", + "path" : "Path", + "comment" : "Comment", + "domain" : "Domain", + "max-age" : "Max-Age", + "secure" : "Secure", + "httponly" : "HttpOnly", + "version" : "Version", + "samesite" : "SameSite", + "partitioned" : "Partitioned", } - _flags = {'secure', 'httponly'} + _flags = {'secure', 'httponly', 'partitioned'} def __init__(self): # Set defaults diff --git a/Lib/test/test_http_cookies.py b/Lib/test/test_http_cookies.py index 8879902a6e2f41..c2b9641e0b1e41 100644 --- a/Lib/test/test_http_cookies.py +++ b/Lib/test/test_http_cookies.py @@ -159,6 +159,14 @@ def test_set_secure_httponly_attrs(self): self.assertEqual(C.output(), 'Set-Cookie: Customer="WILE_E_COYOTE"; HttpOnly; Secure') + def test_set_secure_httponly_attrs(self): + C = cookies.SimpleCookie('Customer="WILE_E_COYOTE"') + C['Customer']['secure'] = True + C['Customer']['httponly'] = True + C['Customer']['partitioned'] = True + self.assertEqual(C.output(), + 'Set-Cookie: Customer="WILE_E_COYOTE"; HttpOnly; Partitioned; Secure') + def test_samesite_attrs(self): samesite_values = ['Strict', 'Lax', 'strict', 'lax'] for val in samesite_values: From 14d9a5c72931a4d6f120d8c5987b9bc81e2d8c7b Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 15:53:26 +0000 Subject: [PATCH 08/14] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2023-12-04-15-53-25.gh-issue-112713.Zrhv77.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-12-04-15-53-25.gh-issue-112713.Zrhv77.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-12-04-15-53-25.gh-issue-112713.Zrhv77.rst b/Misc/NEWS.d/next/Core and Builtins/2023-12-04-15-53-25.gh-issue-112713.Zrhv77.rst new file mode 100644 index 00000000000000..d00a7f9446da1a --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-12-04-15-53-25.gh-issue-112713.Zrhv77.rst @@ -0,0 +1 @@ +Added support for the ``Partitioned`` cookie flag to the ``http.cookies`` module. From e622cda7cc64bb2d11ef9f22ce45ab56e7bb0e19 Mon Sep 17 00:00:00 2001 From: Giles Copp Date: Mon, 4 Dec 2023 11:09:14 -0500 Subject: [PATCH 09/14] Fix invalid test name function --- Lib/test/test_http_cookies.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_http_cookies.py b/Lib/test/test_http_cookies.py index c2b9641e0b1e41..82c5254bb5da84 100644 --- a/Lib/test/test_http_cookies.py +++ b/Lib/test/test_http_cookies.py @@ -159,7 +159,7 @@ def test_set_secure_httponly_attrs(self): self.assertEqual(C.output(), 'Set-Cookie: Customer="WILE_E_COYOTE"; HttpOnly; Secure') - def test_set_secure_httponly_attrs(self): + def test_set_secure_httponly_partitioned_attrs(self): C = cookies.SimpleCookie('Customer="WILE_E_COYOTE"') C['Customer']['secure'] = True C['Customer']['httponly'] = True From 1949596641911e7eef9bb9a951abc8453ec9a0fa Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith [Google LLC]" Date: Tue, 13 Feb 2024 17:52:02 -0800 Subject: [PATCH 10/14] Wordsmith the docs and include a link to the spec. --- Doc/library/http.cookies.rst | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Doc/library/http.cookies.rst b/Doc/library/http.cookies.rst index ad489a8b3c35b3..14bde443c433b4 100644 --- a/Doc/library/http.cookies.rst +++ b/Doc/library/http.cookies.rst @@ -153,11 +153,16 @@ Morsel Objects attacks. Valid values for this attribute are "Strict" and "Lax". The attribute :attr:`partitioned` indicates to user agents that these - cross-site cookies should only be available in the same top-level context - that the cookie was first set in. Must also set ``Secure`` and ``Path=/``. + cross-site cookies *should* only be available in the same top-level context + that the cookie was first set in. For this to be accepted by the user agent, + you **must** also set both ``Secure`` and ``Path=/``. 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. + registrable domain. Read + `CHIPS (Cookies Having Independent Partitioned State)`_ + for full details and examples. + + .. _CHIPS (Cookies Having Independent Partitioned State): https://github.com/privacycg/CHIPS/blob/main/README.md The keys are case-insensitive and their default value is ``''``. From 9f3c9b096e20b650a06a6e01528f455d327a1ac3 Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith [Google LLC]" Date: Tue, 13 Feb 2024 17:54:50 -0800 Subject: [PATCH 11/14] Style: Don't retain unusual hand spacing. --- Lib/http/cookies.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Lib/http/cookies.py b/Lib/http/cookies.py index 617eb25daf03d8..e547e3c35e6ee4 100644 --- a/Lib/http/cookies.py +++ b/Lib/http/cookies.py @@ -255,16 +255,16 @@ class Morsel(dict): # variant on the left to the appropriate traditional # formatting on the right. _reserved = { - "expires" : "expires", - "path" : "Path", - "comment" : "Comment", - "domain" : "Domain", - "max-age" : "Max-Age", - "secure" : "Secure", - "httponly" : "HttpOnly", - "version" : "Version", - "samesite" : "SameSite", - "partitioned" : "Partitioned", + "expires": "expires", + "path": "Path", + "comment": "Comment", + "domain": "Domain", + "max-age": "Max-Age", + "secure": "Secure", + "httponly": "HttpOnly", + "version": "Version", + "samesite": "SameSite", + "partitioned": "Partitioned", } _flags = {'secure', 'httponly', 'partitioned'} From f03bdd934b1960f415b411dfb7c1d181787afdaf Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith [Google LLC]" Date: Tue, 13 Feb 2024 18:01:44 -0800 Subject: [PATCH 12/14] News ReST improvements. --- .../2023-12-04-15-53-25.gh-issue-112713.Zrhv77.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-12-04-15-53-25.gh-issue-112713.Zrhv77.rst b/Misc/NEWS.d/next/Core and Builtins/2023-12-04-15-53-25.gh-issue-112713.Zrhv77.rst index d00a7f9446da1a..ee1f33f95647bd 100644 --- a/Misc/NEWS.d/next/Core and Builtins/2023-12-04-15-53-25.gh-issue-112713.Zrhv77.rst +++ b/Misc/NEWS.d/next/Core and Builtins/2023-12-04-15-53-25.gh-issue-112713.Zrhv77.rst @@ -1 +1 @@ -Added support for the ``Partitioned`` cookie flag to the ``http.cookies`` module. +Added support for the ``Partitioned`` cookie flag in :mod:`http.cookies`. From 097fc45295c8778e80f5577674d463419eeb3b22 Mon Sep 17 00:00:00 2001 From: Giles Copp Date: Mon, 9 Sep 2024 11:10:02 -0400 Subject: [PATCH 13/14] Remove Path=/ mandatory requirement from the docs --- Doc/library/http.cookies.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Doc/library/http.cookies.rst b/Doc/library/http.cookies.rst index 14bde443c433b4..023dcd6dc9eeaf 100644 --- a/Doc/library/http.cookies.rst +++ b/Doc/library/http.cookies.rst @@ -155,7 +155,8 @@ Morsel Objects The attribute :attr:`partitioned` indicates to user agents that these cross-site cookies *should* only be available in the same top-level context that the cookie was first set in. For this to be accepted by the user agent, - you **must** also set both ``Secure`` and ``Path=/``. + you **must** also set ``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. Read From 4fdecb510589183b377fb0e2e7ce8bf96f196c1b Mon Sep 17 00:00:00 2001 From: Giles Copp Date: Tue, 10 Dec 2024 11:01:47 -0500 Subject: [PATCH 14/14] Move morsel docs version to 3.1.4, and revert spacing changes --- Doc/library/http.cookies.rst | 2 +- Lib/http/cookies.py | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Doc/library/http.cookies.rst b/Doc/library/http.cookies.rst index 023dcd6dc9eeaf..8ee3db2066ba60 100644 --- a/Doc/library/http.cookies.rst +++ b/Doc/library/http.cookies.rst @@ -179,7 +179,7 @@ Morsel Objects .. versionchanged:: 3.8 Added support for the :attr:`samesite` attribute. - .. versionchanged:: 3.13 + .. versionchanged:: 3.14 Added support for the :attr:`partitioned` attribute. diff --git a/Lib/http/cookies.py b/Lib/http/cookies.py index e547e3c35e6ee4..7c591197c929ec 100644 --- a/Lib/http/cookies.py +++ b/Lib/http/cookies.py @@ -255,15 +255,15 @@ class Morsel(dict): # variant on the left to the appropriate traditional # formatting on the right. _reserved = { - "expires": "expires", - "path": "Path", - "comment": "Comment", - "domain": "Domain", - "max-age": "Max-Age", - "secure": "Secure", - "httponly": "HttpOnly", - "version": "Version", - "samesite": "SameSite", + "expires" : "expires", + "path" : "Path", + "comment" : "Comment", + "domain" : "Domain", + "max-age" : "Max-Age", + "secure" : "Secure", + "httponly" : "HttpOnly", + "version" : "Version", + "samesite" : "SameSite", "partitioned": "Partitioned", }