diff --git a/Doc/library/http.cookies.rst b/Doc/library/http.cookies.rst index fb8317ad59e..f3457a0cdc7 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 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 ``''``. .. versionchanged:: 3.5 @@ -153,6 +158,9 @@ Morsel Objects :attr:`~Morsel.coded_value` are read-only. Use :meth:`~Morsel.set` for setting them. + .. versionchanged:: 3.8 + Added support for the :attr:`samesite` attribute. + .. attribute:: Morsel.value diff --git a/Lib/http/cookies.py b/Lib/http/cookies.py index 7e0259ee32e..4a44db8475e 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 2ff690243fc..447f883390f 100644 --- a/Lib/test/test_http_cookies.py +++ b/Lib/test/test_http_cookies.py @@ -121,6 +121,19 @@ class CookieTests(unittest.TestCase): self.assertEqual(C.output(), 'Set-Cookie: Customer="WILE_E_COYOTE"; HttpOnly; Secure') + def test_samesite_attrs(self): + samesite_values = ['Strict', 'Lax', '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) + + 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() C.load('eggs=scrambled; Path=/bacon') diff --git a/Misc/ACKS b/Misc/ACKS index b951446bab7..8b2931f0bd3 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 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 00000000000..a679cd91194 --- /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.