diff --git a/Doc/library/http.cookies.rst b/Doc/library/http.cookies.rst index fb8317ad59e6f8..864010656e0444 100644 --- a/Doc/library/http.cookies.rst +++ b/Doc/library/http.cookies.rst @@ -137,11 +137,17 @@ 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 @@ -153,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 diff --git a/Lib/http/cookies.py b/Lib/http/cookies.py index 7e0259ee32e463..4a44db8475ead4 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..4987ec848fd54c 100644 --- a/Lib/test/test_http_cookies.py +++ b/Lib/test/test_http_cookies.py @@ -121,6 +121,15 @@ def test_set_secure_httponly_attrs(self): self.assertEqual(C.output(), 'Set-Cookie: Customer="WILE_E_COYOTE"; HttpOnly; Secure') + 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() C.load('eggs=scrambled; Path=/bacon') 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..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.