From ef83909c965ba2a042fcef23f06a54ab7574d7f5 Mon Sep 17 00:00:00 2001 From: Akash Shende Date: Tue, 21 Feb 2017 16:26:57 +0530 Subject: [PATCH 1/8] 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 ca21476da62bb7..63889bbf256be1 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 c8bc13550876e899d0c1e043062841b717020e22 Mon Sep 17 00:00:00 2001 From: Akash Shende Date: Tue, 21 Feb 2017 22:17:26 +0530 Subject: [PATCH 2/8] 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 c064da49b267b74d0d342c6bc44bd8cfec39a183 Mon Sep 17 00:00:00 2001 From: Akash Shende Date: Tue, 21 Feb 2017 22:23:50 +0530 Subject: [PATCH 3/8] 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 364ea4634d529c70eb4993a6818f7e4cb91d8f53 Mon Sep 17 00:00:00 2001 From: Akash Shende Date: Wed, 22 Feb 2017 00:20:00 +0530 Subject: [PATCH 4/8] Updated News and contributors --- Misc/ACKS | 1 + Misc/NEWS | 3 +++ 2 files changed, 4 insertions(+) diff --git a/Misc/ACKS b/Misc/ACKS index b7f1282c69c0ce..2052b3db43e56e 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1396,6 +1396,7 @@ Varun Sharma Daniel Shaulov Vlad Shcherbina Justin Sheehy +Akash Shende Charlie Shepherd Bruce Sherwood Alexander Shigin diff --git a/Misc/NEWS b/Misc/NEWS index 4f19e75aeaa8fc..8ddecfa2101465 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -677,6 +677,9 @@ Library - Issue #24142: Reading a corrupt config file left configparser in an invalid state. Original patch by Florian Höch. +- bpo-29613: http.cookies.Morsel now supports SameSite cookies. + Patch by Akash Shende. + Windows ------- From c3890a22fc682ca1936006808a1efb8c987f5e49 Mon Sep 17 00:00:00 2001 From: Akash Shende Date: Wed, 22 Feb 2017 08:31:59 +0530 Subject: [PATCH 5/8] Added version changed details. --- Doc/library/http.cookies.rst | 9 ++++++--- Misc/NEWS | 5 ++--- 2 files changed, 8 insertions(+), 6 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 ``''``. diff --git a/Misc/NEWS b/Misc/NEWS index 8ddecfa2101465..4f3baced81c4b5 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -263,6 +263,8 @@ Library - Issue #16285: urrlib.parse.quote is now based on RFC 3986 and hence includes '~' in the set of characters that is not quoted by default. Patch by Christian Theune and Ratnadeep Debnath. +- bpo-29613: http.cookies.Morsel now supports SameSite cookies. + Patch by Akash Shende. - bpo-29532: Altering a kwarg dictionary passed to functools.partial() no longer affects a partial object after creation. @@ -677,9 +679,6 @@ Library - Issue #24142: Reading a corrupt config file left configparser in an invalid state. Original patch by Florian Höch. -- bpo-29613: http.cookies.Morsel now supports SameSite cookies. - Patch by Akash Shende. - Windows ------- From 6ed3f3f5ae04f0b9af42863206a276dd845acac1 Mon Sep 17 00:00:00 2001 From: Akash Shende Date: Wed, 22 Feb 2017 10:36:46 +0530 Subject: [PATCH 6/8] 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 aa54e5018b68233ce4a69627f26ecb7308d628bc Mon Sep 17 00:00:00 2001 From: Akash Shende Date: Wed, 22 Feb 2017 12:36:17 +0530 Subject: [PATCH 7/8] 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 a6cbc20f3df0b09665ac213ce11b49026f06ebdc Mon Sep 17 00:00:00 2001 From: Akash Shende Date: Wed, 22 Feb 2017 14:51:22 +0530 Subject: [PATCH 8/8] 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 63889bbf256be1..4987ec848fd54c 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()