Fixed #30862 -- Allowed setting SameSite cookies flags to 'none'.
Thanks Florian Apolloner and Carlton Gibson for reviews.
This commit is contained in:
parent
14e690ae5a
commit
b33bfc3839
|
@ -197,8 +197,8 @@ class HttpResponseBase:
|
||||||
if httponly:
|
if httponly:
|
||||||
self.cookies[key]['httponly'] = True
|
self.cookies[key]['httponly'] = True
|
||||||
if samesite:
|
if samesite:
|
||||||
if samesite.lower() not in ('lax', 'strict'):
|
if samesite.lower() not in ('lax', 'none', 'strict'):
|
||||||
raise ValueError('samesite must be "lax" or "strict".')
|
raise ValueError('samesite must be "lax", "none", or "strict".')
|
||||||
self.cookies[key]['samesite'] = samesite
|
self.cookies[key]['samesite'] = samesite
|
||||||
|
|
||||||
def setdefault(self, key, value):
|
def setdefault(self, key, value):
|
||||||
|
|
|
@ -833,9 +833,16 @@ Methods
|
||||||
isn't supported by all browsers, so it's not a replacement for Django's
|
isn't supported by all browsers, so it's not a replacement for Django's
|
||||||
CSRF protection, but rather a defense in depth measure.
|
CSRF protection, but rather a defense in depth measure.
|
||||||
|
|
||||||
|
Use ``samesite='None'`` (string) to explicitly state that this cookie is
|
||||||
|
sent with all same-site and cross-site requests.
|
||||||
|
|
||||||
.. _HttpOnly: https://www.owasp.org/index.php/HttpOnly
|
.. _HttpOnly: https://www.owasp.org/index.php/HttpOnly
|
||||||
.. _SameSite: https://www.owasp.org/index.php/SameSite
|
.. _SameSite: https://www.owasp.org/index.php/SameSite
|
||||||
|
|
||||||
|
.. versionchanged:: 3.1
|
||||||
|
|
||||||
|
Using ``samesite='None'`` (string) was allowed.
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
|
|
||||||
:rfc:`RFC 6265 <6265#section-6.1>` states that user agents should
|
:rfc:`RFC 6265 <6265#section-6.1>` states that user agents should
|
||||||
|
@ -853,6 +860,10 @@ Methods
|
||||||
you will need to remember to pass it to the corresponding
|
you will need to remember to pass it to the corresponding
|
||||||
:meth:`HttpRequest.get_signed_cookie` call.
|
:meth:`HttpRequest.get_signed_cookie` call.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.1
|
||||||
|
|
||||||
|
Using ``samesite='None'`` (string) was allowed.
|
||||||
|
|
||||||
.. method:: HttpResponse.delete_cookie(key, path='/', domain=None)
|
.. method:: HttpResponse.delete_cookie(key, path='/', domain=None)
|
||||||
|
|
||||||
Deletes the cookie with the given key. Fails silently if the key doesn't
|
Deletes the cookie with the given key. Fails silently if the key doesn't
|
||||||
|
|
|
@ -383,6 +383,10 @@ cookie from being sent in cross-site requests.
|
||||||
|
|
||||||
See :setting:`SESSION_COOKIE_SAMESITE` for details about ``SameSite``.
|
See :setting:`SESSION_COOKIE_SAMESITE` for details about ``SameSite``.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.1
|
||||||
|
|
||||||
|
Setting ``CSRF_COOKIE_SAMESITE = 'None'`` was allowed.
|
||||||
|
|
||||||
.. setting:: CSRF_COOKIE_SECURE
|
.. setting:: CSRF_COOKIE_SECURE
|
||||||
|
|
||||||
``CSRF_COOKIE_SECURE``
|
``CSRF_COOKIE_SECURE``
|
||||||
|
@ -1862,6 +1866,10 @@ cookie from being sent in cross-site requests.
|
||||||
|
|
||||||
See :setting:`SESSION_COOKIE_SAMESITE` for details about ``SameSite``.
|
See :setting:`SESSION_COOKIE_SAMESITE` for details about ``SameSite``.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.1
|
||||||
|
|
||||||
|
Setting ``LANGUAGE_COOKIE_SAMESITE = 'None'`` was allowed.
|
||||||
|
|
||||||
.. setting:: LANGUAGE_COOKIE_SECURE
|
.. setting:: LANGUAGE_COOKIE_SECURE
|
||||||
|
|
||||||
``LANGUAGE_COOKIE_SECURE``
|
``LANGUAGE_COOKIE_SECURE``
|
||||||
|
@ -3208,7 +3216,14 @@ Possible values for the setting are:
|
||||||
regular link from an external website and be blocked in CSRF-prone request
|
regular link from an external website and be blocked in CSRF-prone request
|
||||||
methods (e.g. ``POST``).
|
methods (e.g. ``POST``).
|
||||||
|
|
||||||
* ``None``: disables the flag.
|
* ``'None'`` (string): the session cookie will be sent with all same-site and
|
||||||
|
cross-site requests.
|
||||||
|
|
||||||
|
* ``False``: disables the flag.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.1
|
||||||
|
|
||||||
|
Setting ``SESSION_COOKIE_SAMESITE = 'None'`` was allowed.
|
||||||
|
|
||||||
.. _SameSite: https://www.owasp.org/index.php/SameSite
|
.. _SameSite: https://www.owasp.org/index.php/SameSite
|
||||||
|
|
||||||
|
|
|
@ -105,7 +105,9 @@ Minor features
|
||||||
:mod:`django.contrib.sessions`
|
:mod:`django.contrib.sessions`
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
* ...
|
* The :setting:`SESSION_COOKIE_SAMESITE` setting now allows ``'None'`` (string)
|
||||||
|
value to explicitly state that the cookie is sent with all same-site and
|
||||||
|
cross-site requests.
|
||||||
|
|
||||||
:mod:`django.contrib.sitemaps`
|
:mod:`django.contrib.sitemaps`
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -141,7 +143,9 @@ Cache
|
||||||
CSRF
|
CSRF
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
* ...
|
* The :setting:`CSRF_COOKIE_SAMESITE` setting now allows ``'None'`` (string)
|
||||||
|
value to explicitly state that the cookie is sent with all same-site and
|
||||||
|
cross-site requests.
|
||||||
|
|
||||||
Email
|
Email
|
||||||
~~~~~
|
~~~~~
|
||||||
|
@ -173,7 +177,9 @@ Generic Views
|
||||||
Internationalization
|
Internationalization
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
* ...
|
* The :setting:`LANGUAGE_COOKIE_SAMESITE` setting now allows ``'None'``
|
||||||
|
(string) value to explicitly state that the cookie is sent with all same-site
|
||||||
|
and cross-site requests.
|
||||||
|
|
||||||
Logging
|
Logging
|
||||||
~~~~~~~
|
~~~~~~~
|
||||||
|
@ -232,6 +238,10 @@ Requests and Responses
|
||||||
* If :setting:`ALLOWED_HOSTS` is empty and ``DEBUG=True``, subdomains of
|
* If :setting:`ALLOWED_HOSTS` is empty and ``DEBUG=True``, subdomains of
|
||||||
localhost are now allowed in the ``Host`` header, e.g. ``static.localhost``.
|
localhost are now allowed in the ``Host`` header, e.g. ``static.localhost``.
|
||||||
|
|
||||||
|
* :meth:`.HttpResponse.set_cookie` and :meth:`.HttpResponse.set_signed_cookie`
|
||||||
|
now allow using ``samesite='None'`` (string) to explicitly state that the
|
||||||
|
cookie is sent with all same-site and cross-site requests.
|
||||||
|
|
||||||
Serialization
|
Serialization
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -81,13 +81,16 @@ class SetCookieTests(SimpleTestCase):
|
||||||
|
|
||||||
def test_samesite(self):
|
def test_samesite(self):
|
||||||
response = HttpResponse()
|
response = HttpResponse()
|
||||||
|
response.set_cookie('example', samesite='None')
|
||||||
|
self.assertEqual(response.cookies['example']['samesite'], 'None')
|
||||||
response.set_cookie('example', samesite='Lax')
|
response.set_cookie('example', samesite='Lax')
|
||||||
self.assertEqual(response.cookies['example']['samesite'], 'Lax')
|
self.assertEqual(response.cookies['example']['samesite'], 'Lax')
|
||||||
response.set_cookie('example', samesite='strict')
|
response.set_cookie('example', samesite='strict')
|
||||||
self.assertEqual(response.cookies['example']['samesite'], 'strict')
|
self.assertEqual(response.cookies['example']['samesite'], 'strict')
|
||||||
|
|
||||||
def test_invalid_samesite(self):
|
def test_invalid_samesite(self):
|
||||||
with self.assertRaisesMessage(ValueError, 'samesite must be "lax" or "strict".'):
|
msg = 'samesite must be "lax", "none", or "strict".'
|
||||||
|
with self.assertRaisesMessage(ValueError, msg):
|
||||||
HttpResponse().set_cookie('example', samesite='invalid')
|
HttpResponse().set_cookie('example', samesite='invalid')
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue