From 89c08214617157d7d5ebd7bd08d7f68db0ed2e4a Mon Sep 17 00:00:00 2001 From: Akash Shende Date: Tue, 21 Feb 2017 16:26:57 +0530 Subject: [PATCH 01/11] bpo-29613: Added support for SameSite cookies Implemented as per draft https://tools.ietf.org/html/draft-west-first-party-cookies-07 --- Lib/http/cookies.py | 1 + Lib/test/test_http_cookies.py | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/Lib/http/cookies.py b/Lib/http/cookies.py index 7e0259ee32e463..2404cb48df2c87 100644 --- a/Lib/http/cookies.py +++ b/Lib/http/cookies.py @@ -281,6 +281,7 @@ class Morsel(dict): "secure" : "Secure", "httponly" : "HttpOnly", "version" : "Version", + "samesite" : "SameSite" } _flags = {'secure', 'httponly'} diff --git a/Lib/test/test_http_cookies.py b/Lib/test/test_http_cookies.py index 2ff690243fc30e..1ae1256cc53891 100644 --- a/Lib/test/test_http_cookies.py +++ b/Lib/test/test_http_cookies.py @@ -121,6 +121,18 @@ def test_set_secure_httponly_attrs(self): self.assertEqual(C.output(), 'Set-Cookie: Customer="WILE_E_COYOTE"; HttpOnly; Secure') + def test_samesite_strict_attrs(self): + C = cookies.SimpleCookie('Customer="WILE_E_COYOTE"') + C['Customer']['samesite'] = "Strict" + self.assertEqual(C.output(), + 'Set-Cookie: Customer="WILE_E_COYOTE"; SameSite=Strict') + + def test_samesite_lax_attrs(self): + C = cookies.SimpleCookie('Customer="WILE_E_COYOTE"') + C['Customer']['samesite'] = "Lax" + self.assertEqual(C.output(), + 'Set-Cookie: Customer="WILE_E_COYOTE"; SameSite=Lax') + def test_secure_httponly_false_if_not_present(self): C = cookies.SimpleCookie() C.load('eggs=scrambled; Path=/bacon') From 3f1b1304e0c98a0ab5dc895e310783fe3e739873 Mon Sep 17 00:00:00 2001 From: Akash Shende Date: Tue, 21 Feb 2017 22:17:26 +0530 Subject: [PATCH 02/11] Documented SameSite And suggestions by members. --- Doc/library/http.cookies.rst | 5 +++++ Lib/http/cookies.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Doc/library/http.cookies.rst b/Doc/library/http.cookies.rst index fb8317ad59e6f8..98c3a794407c3b 100644 --- a/Doc/library/http.cookies.rst +++ b/Doc/library/http.cookies.rst @@ -137,11 +137,16 @@ Morsel Objects * ``secure`` * ``version`` * ``httponly`` + * ``samesite`` The attribute :attr:`httponly` specifies that the cookie is only transferred in HTTP requests, and is not accessible through JavaScript. This is intended to mitigate some forms of cross-site scripting. + The attribute:attr:`samesite` specifies that browser is not allowed to send the + cookie along with cross-site requests. This help to mitigate CSRF attacks. Valid + values for this attribute are "Strict" and "Lax". + The keys are case-insensitive and their default value is ``''``. .. versionchanged:: 3.5 diff --git a/Lib/http/cookies.py b/Lib/http/cookies.py index 2404cb48df2c87..4a44db8475ead4 100644 --- a/Lib/http/cookies.py +++ b/Lib/http/cookies.py @@ -281,7 +281,7 @@ class Morsel(dict): "secure" : "Secure", "httponly" : "HttpOnly", "version" : "Version", - "samesite" : "SameSite" + "samesite" : "SameSite", } _flags = {'secure', 'httponly'} From 7d69cd9ff430f6518413b9b114e22df5b244d748 Mon Sep 17 00:00:00 2001 From: Akash Shende Date: Tue, 21 Feb 2017 22:23:50 +0530 Subject: [PATCH 03/11] Missing space :( --- Doc/library/http.cookies.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/http.cookies.rst b/Doc/library/http.cookies.rst index 98c3a794407c3b..7fd87f3e8e4616 100644 --- a/Doc/library/http.cookies.rst +++ b/Doc/library/http.cookies.rst @@ -143,7 +143,7 @@ Morsel Objects in HTTP requests, and is not accessible through JavaScript. This is intended to mitigate some forms of cross-site scripting. - The attribute:attr:`samesite` specifies that browser is not allowed to send the + The attribute :attr:`samesite` specifies that browser is not allowed to send the cookie along with cross-site requests. This help to mitigate CSRF attacks. Valid values for this attribute are "Strict" and "Lax". From b58531586606e1456ad84a3e09f0f8a6b6b9edf0 Mon Sep 17 00:00:00 2001 From: Akash Shende Date: Wed, 22 Feb 2017 00:20:00 +0530 Subject: [PATCH 04/11] Updated News and contributors --- Misc/ACKS | 1 + 1 file changed, 1 insertion(+) diff --git a/Misc/ACKS b/Misc/ACKS index b951446bab7b6e..8b2931f0bd35ef 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1461,6 +1461,7 @@ Varun Sharma Daniel Shaulov Vlad Shcherbina Justin Sheehy +Akash Shende Charlie Shepherd Bruce Sherwood Alexander Shigin From 81446f6a4a67248fd5c8780b62df65468fe462fb Mon Sep 17 00:00:00 2001 From: Akash Shende Date: Wed, 22 Feb 2017 08:31:59 +0530 Subject: [PATCH 05/11] Added version changed details. --- Doc/library/http.cookies.rst | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Doc/library/http.cookies.rst b/Doc/library/http.cookies.rst index 7fd87f3e8e4616..ab408b617eba2d 100644 --- a/Doc/library/http.cookies.rst +++ b/Doc/library/http.cookies.rst @@ -143,9 +143,12 @@ Morsel Objects in HTTP requests, and is not accessible through JavaScript. This is intended to mitigate some forms of cross-site scripting. - The attribute :attr:`samesite` specifies that browser is not allowed to send the - cookie along with cross-site requests. This help to mitigate CSRF attacks. Valid - values for this attribute are "Strict" and "Lax". + .. versionchanged:: 3.7 + Added support for :attr:`samesite` attribute. + + The attribute :attr:`samesite` specifies that browser is not allowed to send the + cookie along with cross-site requests. This help to mitigate CSRF attacks. Valid + values for this attribute are "Strict" and "Lax". The keys are case-insensitive and their default value is ``''``. From 21d0bdaa5506af2877f53a33b429938b8f58e515 Mon Sep 17 00:00:00 2001 From: Akash Shende Date: Wed, 22 Feb 2017 10:36:46 +0530 Subject: [PATCH 06/11] Fix in documentation --- Doc/library/http.cookies.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/library/http.cookies.rst b/Doc/library/http.cookies.rst index ab408b617eba2d..aefa6f7e1a3062 100644 --- a/Doc/library/http.cookies.rst +++ b/Doc/library/http.cookies.rst @@ -143,13 +143,13 @@ Morsel Objects in HTTP requests, and is not accessible through JavaScript. This is intended to mitigate some forms of cross-site scripting. + The attribute :attr:`samesite` specifies that browser is not allowed to send the + cookie along with cross-site requests. This help to mitigate CSRF attacks. Valid + values for this attribute are "Strict" and "Lax". + .. versionchanged:: 3.7 Added support for :attr:`samesite` attribute. - The attribute :attr:`samesite` specifies that browser is not allowed to send the - cookie along with cross-site requests. This help to mitigate CSRF attacks. Valid - values for this attribute are "Strict" and "Lax". - The keys are case-insensitive and their default value is ``''``. .. versionchanged:: 3.5 From cc06dd159c3a46191fd0504908a08dc656513808 Mon Sep 17 00:00:00 2001 From: Akash Shende Date: Wed, 22 Feb 2017 12:36:17 +0530 Subject: [PATCH 07/11] fix in documentation --- Doc/library/http.cookies.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Doc/library/http.cookies.rst b/Doc/library/http.cookies.rst index aefa6f7e1a3062..864010656e0444 100644 --- a/Doc/library/http.cookies.rst +++ b/Doc/library/http.cookies.rst @@ -147,8 +147,6 @@ Morsel Objects cookie along with cross-site requests. This help to mitigate CSRF attacks. Valid values for this attribute are "Strict" and "Lax". - .. versionchanged:: 3.7 - Added support for :attr:`samesite` attribute. The keys are case-insensitive and their default value is ``''``. @@ -161,6 +159,9 @@ Morsel Objects :attr:`~Morsel.coded_value` are read-only. Use :meth:`~Morsel.set` for setting them. + .. versionchanged:: 3.7 + Added support for :attr:`samesite` attribute. + .. attribute:: Morsel.value From dc750c3452acec05677020fbf5e7b516883d997c Mon Sep 17 00:00:00 2001 From: Akash Shende Date: Wed, 22 Feb 2017 14:51:22 +0530 Subject: [PATCH 08/11] Clubbed test cases for same attribute into single. --- Lib/test/test_http_cookies.py | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/Lib/test/test_http_cookies.py b/Lib/test/test_http_cookies.py index 1ae1256cc53891..1792a04cc04797 100644 --- a/Lib/test/test_http_cookies.py +++ b/Lib/test/test_http_cookies.py @@ -121,17 +121,14 @@ def test_set_secure_httponly_attrs(self): self.assertEqual(C.output(), 'Set-Cookie: Customer="WILE_E_COYOTE"; HttpOnly; Secure') - def test_samesite_strict_attrs(self): - C = cookies.SimpleCookie('Customer="WILE_E_COYOTE"') - C['Customer']['samesite'] = "Strict" - self.assertEqual(C.output(), - 'Set-Cookie: Customer="WILE_E_COYOTE"; SameSite=Strict') - - def test_samesite_lax_attrs(self): - C = cookies.SimpleCookie('Customer="WILE_E_COYOTE"') - C['Customer']['samesite'] = "Lax" - self.assertEqual(C.output(), - 'Set-Cookie: Customer="WILE_E_COYOTE"; SameSite=Lax') + def test_samesite_attrs(self): + samesite_values = ("Strict", "Lax") + for val in samesite_values: + with self.subTest(val=val): + C = cookies.SimpleCookie('Customer="WILE_E_COYOTE"') + C['Customer']['samesite'] = val + self.assertEqual(C.output(), + 'Set-Cookie: Customer="WILE_E_COYOTE"; SameSite=%s' % val) def test_secure_httponly_false_if_not_present(self): C = cookies.SimpleCookie() From d496c01ac99fcc834240c4b42848b0065c7017de Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 7 Apr 2018 13:49:53 -0400 Subject: [PATCH 09/11] Updates --- Doc/library/http.cookies.rst | 2 +- .../next/Library/2018-04-07-13-49-39.bpo-29613.r6FDnB.rst | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2018-04-07-13-49-39.bpo-29613.r6FDnB.rst diff --git a/Doc/library/http.cookies.rst b/Doc/library/http.cookies.rst index 864010656e0444..78c9b9414b191a 100644 --- a/Doc/library/http.cookies.rst +++ b/Doc/library/http.cookies.rst @@ -159,7 +159,7 @@ Morsel Objects :attr:`~Morsel.coded_value` are read-only. Use :meth:`~Morsel.set` for setting them. - .. versionchanged:: 3.7 + .. versionchanged:: 3.8 Added support for :attr:`samesite` attribute. diff --git a/Misc/NEWS.d/next/Library/2018-04-07-13-49-39.bpo-29613.r6FDnB.rst b/Misc/NEWS.d/next/Library/2018-04-07-13-49-39.bpo-29613.r6FDnB.rst new file mode 100644 index 00000000000000..a679cd91194fa9 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-04-07-13-49-39.bpo-29613.r6FDnB.rst @@ -0,0 +1,2 @@ +Added support for the ``SameSite`` cookie flag to the ``http.cookies`` +module. From dcd0afa15caf520111ab43ad6855c00f5cf77113 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 7 Apr 2018 13:57:48 -0400 Subject: [PATCH 10/11] Style nits + expand tests --- Lib/test/test_http_cookies.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_http_cookies.py b/Lib/test/test_http_cookies.py index 1792a04cc04797..fbc78c9d6e1bd2 100644 --- a/Lib/test/test_http_cookies.py +++ b/Lib/test/test_http_cookies.py @@ -122,13 +122,17 @@ def test_set_secure_httponly_attrs(self): 'Set-Cookie: Customer="WILE_E_COYOTE"; HttpOnly; Secure') def test_samesite_attrs(self): - samesite_values = ("Strict", "Lax") + samesite_values = ['Strict', 'Lax'] for val in samesite_values: with self.subTest(val=val): C = cookies.SimpleCookie('Customer="WILE_E_COYOTE"') C['Customer']['samesite'] = val self.assertEqual(C.output(), - 'Set-Cookie: Customer="WILE_E_COYOTE"; SameSite=%s' % val) + 'Set-Cookie: Customer="WILE_E_COYOTE"; SameSite=%s' % val) + + C = cookies.SimpleCookie() + C.load('Customer="WILL_E_COYOTE"; SameSite=%s' % val) + self.assertEqual(C['Customer']['samesite'], val) def test_secure_httponly_false_if_not_present(self): C = cookies.SimpleCookie() From 9259d2e401b6ed17ba7361897ff2dd0e18c23929 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 7 Apr 2018 14:27:35 -0400 Subject: [PATCH 11/11] review feedback --- Doc/library/http.cookies.rst | 9 ++++----- Lib/test/test_http_cookies.py | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Doc/library/http.cookies.rst b/Doc/library/http.cookies.rst index 78c9b9414b191a..f3457a0cdc7bc4 100644 --- a/Doc/library/http.cookies.rst +++ b/Doc/library/http.cookies.rst @@ -143,10 +143,9 @@ Morsel Objects in HTTP requests, and is not accessible through JavaScript. This is intended to mitigate some forms of cross-site scripting. - The attribute :attr:`samesite` specifies that browser is not allowed to send the - cookie along with cross-site requests. This help to mitigate CSRF attacks. Valid - values for this attribute are "Strict" and "Lax". - + The attribute :attr:`samesite` specifies that the browser is not allowed to + send the cookie along with cross-site requests. This helps to mitigate CSRF + attacks. Valid values for this attribute are "Strict" and "Lax". The keys are case-insensitive and their default value is ``''``. @@ -160,7 +159,7 @@ Morsel Objects setting them. .. versionchanged:: 3.8 - Added support for :attr:`samesite` attribute. + Added support for the :attr:`samesite` attribute. .. attribute:: Morsel.value diff --git a/Lib/test/test_http_cookies.py b/Lib/test/test_http_cookies.py index fbc78c9d6e1bd2..447f883390fd73 100644 --- a/Lib/test/test_http_cookies.py +++ b/Lib/test/test_http_cookies.py @@ -122,7 +122,7 @@ def test_set_secure_httponly_attrs(self): 'Set-Cookie: Customer="WILE_E_COYOTE"; HttpOnly; Secure') def test_samesite_attrs(self): - samesite_values = ['Strict', 'Lax'] + samesite_values = ['Strict', 'Lax', 'strict', 'lax'] for val in samesite_values: with self.subTest(val=val): C = cookies.SimpleCookie('Customer="WILE_E_COYOTE"')