Fixed #29406 -- Added support for Referrer-Policy header.
Thanks to James Bennett for the initial implementation.
This commit is contained in:
parent
1edbb6c194
commit
406dba04e1
|
@ -633,5 +633,6 @@ SECURE_HSTS_INCLUDE_SUBDOMAINS = False
|
||||||
SECURE_HSTS_PRELOAD = False
|
SECURE_HSTS_PRELOAD = False
|
||||||
SECURE_HSTS_SECONDS = 0
|
SECURE_HSTS_SECONDS = 0
|
||||||
SECURE_REDIRECT_EXEMPT = []
|
SECURE_REDIRECT_EXEMPT = []
|
||||||
|
SECURE_REFERRER_POLICY = None
|
||||||
SECURE_SSL_HOST = None
|
SECURE_SSL_HOST = None
|
||||||
SECURE_SSL_REDIRECT = False
|
SECURE_SSL_REDIRECT = False
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
from .. import Tags, Warning, register
|
from .. import Error, Tags, Warning, register
|
||||||
|
|
||||||
|
REFERRER_POLICY_VALUES = {
|
||||||
|
'no-referrer', 'no-referrer-when-downgrade', 'origin',
|
||||||
|
'origin-when-cross-origin', 'same-origin', 'strict-origin',
|
||||||
|
'strict-origin-when-cross-origin', 'unsafe-url',
|
||||||
|
}
|
||||||
|
|
||||||
SECRET_KEY_MIN_LENGTH = 50
|
SECRET_KEY_MIN_LENGTH = 50
|
||||||
SECRET_KEY_MIN_UNIQUE_CHARACTERS = 5
|
SECRET_KEY_MIN_UNIQUE_CHARACTERS = 5
|
||||||
|
@ -8,9 +14,9 @@ SECRET_KEY_MIN_UNIQUE_CHARACTERS = 5
|
||||||
W001 = Warning(
|
W001 = Warning(
|
||||||
"You do not have 'django.middleware.security.SecurityMiddleware' "
|
"You do not have 'django.middleware.security.SecurityMiddleware' "
|
||||||
"in your MIDDLEWARE so the SECURE_HSTS_SECONDS, "
|
"in your MIDDLEWARE so the SECURE_HSTS_SECONDS, "
|
||||||
"SECURE_CONTENT_TYPE_NOSNIFF, "
|
"SECURE_CONTENT_TYPE_NOSNIFF, SECURE_BROWSER_XSS_FILTER, "
|
||||||
"SECURE_BROWSER_XSS_FILTER, and SECURE_SSL_REDIRECT settings "
|
"SECURE_REFERRER_POLICY, and SECURE_SSL_REDIRECT settings will have no "
|
||||||
"will have no effect.",
|
"effect.",
|
||||||
id='security.W001',
|
id='security.W001',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -96,6 +102,19 @@ W021 = Warning(
|
||||||
id='security.W021',
|
id='security.W021',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
W022 = Warning(
|
||||||
|
'You have not set the SECURE_REFERRER_POLICY setting. Without this, your '
|
||||||
|
'site will not send a Referrer-Policy header. You should consider '
|
||||||
|
'enabling this header to protect user privacy.',
|
||||||
|
id='security.W022',
|
||||||
|
)
|
||||||
|
|
||||||
|
E023 = Error(
|
||||||
|
'You have set the SECURE_REFERRER_POLICY setting to an invalid value.',
|
||||||
|
hint='Valid values are: {}.'.format(', '.join(sorted(REFERRER_POLICY_VALUES))),
|
||||||
|
id='security.E023',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _security_middleware():
|
def _security_middleware():
|
||||||
return 'django.middleware.security.SecurityMiddleware' in settings.MIDDLEWARE
|
return 'django.middleware.security.SecurityMiddleware' in settings.MIDDLEWARE
|
||||||
|
@ -189,3 +208,18 @@ def check_xframe_deny(app_configs, **kwargs):
|
||||||
@register(Tags.security, deploy=True)
|
@register(Tags.security, deploy=True)
|
||||||
def check_allowed_hosts(app_configs, **kwargs):
|
def check_allowed_hosts(app_configs, **kwargs):
|
||||||
return [] if settings.ALLOWED_HOSTS else [W020]
|
return [] if settings.ALLOWED_HOSTS else [W020]
|
||||||
|
|
||||||
|
|
||||||
|
@register(Tags.security, deploy=True)
|
||||||
|
def check_referrer_policy(app_configs, **kwargs):
|
||||||
|
if _security_middleware():
|
||||||
|
if settings.SECURE_REFERRER_POLICY is None:
|
||||||
|
return [W022]
|
||||||
|
# Support a comma-separated string or iterable of values to allow fallback.
|
||||||
|
if isinstance(settings.SECURE_REFERRER_POLICY, str):
|
||||||
|
values = {v.strip() for v in settings.SECURE_REFERRER_POLICY.split(',')}
|
||||||
|
else:
|
||||||
|
values = set(settings.SECURE_REFERRER_POLICY)
|
||||||
|
if not values <= REFERRER_POLICY_VALUES:
|
||||||
|
return [E023]
|
||||||
|
return []
|
||||||
|
|
|
@ -15,6 +15,7 @@ class SecurityMiddleware(MiddlewareMixin):
|
||||||
self.redirect = settings.SECURE_SSL_REDIRECT
|
self.redirect = settings.SECURE_SSL_REDIRECT
|
||||||
self.redirect_host = settings.SECURE_SSL_HOST
|
self.redirect_host = settings.SECURE_SSL_HOST
|
||||||
self.redirect_exempt = [re.compile(r) for r in settings.SECURE_REDIRECT_EXEMPT]
|
self.redirect_exempt = [re.compile(r) for r in settings.SECURE_REDIRECT_EXEMPT]
|
||||||
|
self.referrer_policy = settings.SECURE_REFERRER_POLICY
|
||||||
self.get_response = get_response
|
self.get_response = get_response
|
||||||
|
|
||||||
def process_request(self, request):
|
def process_request(self, request):
|
||||||
|
@ -43,4 +44,12 @@ class SecurityMiddleware(MiddlewareMixin):
|
||||||
if self.xss_filter:
|
if self.xss_filter:
|
||||||
response.setdefault('X-XSS-Protection', '1; mode=block')
|
response.setdefault('X-XSS-Protection', '1; mode=block')
|
||||||
|
|
||||||
|
if self.referrer_policy:
|
||||||
|
# Support a comma-separated string or iterable of values to allow
|
||||||
|
# fallback.
|
||||||
|
response.setdefault('Referrer-Policy', ','.join(
|
||||||
|
[v.strip() for v in self.referrer_policy.split(',')]
|
||||||
|
if isinstance(self.referrer_policy, str) else self.referrer_policy
|
||||||
|
))
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
|
@ -342,7 +342,8 @@ The following checks are run if you use the :option:`check --deploy` option:
|
||||||
:class:`django.middleware.security.SecurityMiddleware` in your
|
:class:`django.middleware.security.SecurityMiddleware` in your
|
||||||
:setting:`MIDDLEWARE` so the :setting:`SECURE_HSTS_SECONDS`,
|
:setting:`MIDDLEWARE` so the :setting:`SECURE_HSTS_SECONDS`,
|
||||||
:setting:`SECURE_CONTENT_TYPE_NOSNIFF`, :setting:`SECURE_BROWSER_XSS_FILTER`,
|
:setting:`SECURE_CONTENT_TYPE_NOSNIFF`, :setting:`SECURE_BROWSER_XSS_FILTER`,
|
||||||
and :setting:`SECURE_SSL_REDIRECT` settings will have no effect.
|
:setting:`SECURE_REFERRER_POLICY`, and :setting:`SECURE_SSL_REDIRECT`
|
||||||
|
settings will have no effect.
|
||||||
* **security.W002**: You do not have
|
* **security.W002**: You do not have
|
||||||
:class:`django.middleware.clickjacking.XFrameOptionsMiddleware` in your
|
:class:`django.middleware.clickjacking.XFrameOptionsMiddleware` in your
|
||||||
:setting:`MIDDLEWARE`, so your pages will not be served with an
|
:setting:`MIDDLEWARE`, so your pages will not be served with an
|
||||||
|
@ -428,6 +429,11 @@ The following checks are run if you use the :option:`check --deploy` option:
|
||||||
* **security.W021**: You have not set the
|
* **security.W021**: You have not set the
|
||||||
:setting:`SECURE_HSTS_PRELOAD` setting to ``True``. Without this, your site
|
:setting:`SECURE_HSTS_PRELOAD` setting to ``True``. Without this, your site
|
||||||
cannot be submitted to the browser preload list.
|
cannot be submitted to the browser preload list.
|
||||||
|
* **security.W022**: You have not set the :setting:`SECURE_REFERRER_POLICY`
|
||||||
|
setting. Without this, your site will not send a Referrer-Policy header. You
|
||||||
|
should consider enabling this header to protect user privacy.
|
||||||
|
* **security.E023**: You have set the :setting:`SECURE_REFERRER_POLICY` setting
|
||||||
|
to an invalid value.
|
||||||
|
|
||||||
Signals
|
Signals
|
||||||
-------
|
-------
|
||||||
|
|
|
@ -186,6 +186,7 @@ enabled or disabled with a setting.
|
||||||
* :setting:`SECURE_HSTS_PRELOAD`
|
* :setting:`SECURE_HSTS_PRELOAD`
|
||||||
* :setting:`SECURE_HSTS_SECONDS`
|
* :setting:`SECURE_HSTS_SECONDS`
|
||||||
* :setting:`SECURE_REDIRECT_EXEMPT`
|
* :setting:`SECURE_REDIRECT_EXEMPT`
|
||||||
|
* :setting:`SECURE_REFERRER_POLICY`
|
||||||
* :setting:`SECURE_SSL_HOST`
|
* :setting:`SECURE_SSL_HOST`
|
||||||
* :setting:`SECURE_SSL_REDIRECT`
|
* :setting:`SECURE_SSL_REDIRECT`
|
||||||
|
|
||||||
|
@ -241,6 +242,104 @@ If you wish to submit your site to the `browser preload list`_, set the
|
||||||
__ https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security
|
__ https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security
|
||||||
.. _browser preload list: https://hstspreload.org/
|
.. _browser preload list: https://hstspreload.org/
|
||||||
|
|
||||||
|
.. _referrer-policy:
|
||||||
|
|
||||||
|
Referrer Policy
|
||||||
|
~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. versionadded:: 3.0
|
||||||
|
|
||||||
|
Browsers use `the Referer header`__ as a way to send information to a site
|
||||||
|
about how users got there. When a user clicks a link, the browser will send the
|
||||||
|
full URL of the linking page as the referrer. While this can be useful for some
|
||||||
|
purposes -- like figuring out who's linking to your site -- it also can cause
|
||||||
|
privacy concerns by informing one site that a user was visiting another site.
|
||||||
|
|
||||||
|
__ https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referer
|
||||||
|
|
||||||
|
Some browsers have the ability to accept hints about whether they should send
|
||||||
|
the HTTP ``Referer`` header when a user clicks a link; this hint is provided
|
||||||
|
via `the Referrer-Policy header`__. This header can suggest any of three
|
||||||
|
behaviors to browsers:
|
||||||
|
|
||||||
|
__ https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy
|
||||||
|
|
||||||
|
* Full URL: send the entire URL in the ``Referer`` header. For example, if the
|
||||||
|
user is visiting ``https://example.com/page.html``, the ``Referer`` header
|
||||||
|
would contain ``"https://example.com/page.html"``.
|
||||||
|
|
||||||
|
* Origin only: send only the "origin" in the referrer. The origin consists of
|
||||||
|
the scheme, host and (optionally) port number. For example, if the user is
|
||||||
|
visiting ``https://example.com/page.html``, the origin would be
|
||||||
|
``https://example.com/``.
|
||||||
|
|
||||||
|
* No referrer: do not send a ``Referer`` header at all.
|
||||||
|
|
||||||
|
There are two types of conditions this header can tell a browser to watch out
|
||||||
|
for:
|
||||||
|
|
||||||
|
* Same-origin versus cross-origin: a link from ``https://example.com/1.html``
|
||||||
|
to ``https://example.com/2.html`` is same-origin. A link from
|
||||||
|
``https://example.com/page.html`` to ``https://not.example.com/page.html`` is
|
||||||
|
cross-origin.
|
||||||
|
|
||||||
|
* Protocol downgrade: a downgrade occurs if the page containing the link is
|
||||||
|
served via HTTPS, but the page being linked to is not served via HTTPS.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
When your site is served via HTTPS, :ref:`Django's CSRF protection system
|
||||||
|
<using-csrf>` requires the ``Referer`` header to be present, so completely
|
||||||
|
disabling the ``Referer`` header will interfere with CSRF protection. To
|
||||||
|
gain most of the benefits of disabling ``Referer`` headers while also
|
||||||
|
keeping CSRF protection, consider enabling only same-origin referrers.
|
||||||
|
|
||||||
|
``SecurityMiddleware`` can set the ``Referrer-Policy`` header for you, based on
|
||||||
|
the the :setting:`SECURE_REFERRER_POLICY` setting (note spelling: browsers send
|
||||||
|
a ``Referer`` header when a user clicks a link, but the header instructing a
|
||||||
|
browser whether to do so is spelled ``Referrer-Policy``). The valid values for
|
||||||
|
this setting are:
|
||||||
|
|
||||||
|
``no-referrer``
|
||||||
|
Instructs the browser to send no referrer for links clicked on this site.
|
||||||
|
|
||||||
|
``no-referrer-when-downgrade``
|
||||||
|
Instructs the browser to send a full URL as the referrer, but only when no
|
||||||
|
protocol downgrade occurs.
|
||||||
|
|
||||||
|
``origin``
|
||||||
|
Instructs the browser to send only the origin, not the full URL, as the
|
||||||
|
referrer.
|
||||||
|
|
||||||
|
``origin-when-cross-origin``
|
||||||
|
Instructs the browser to send the full URL as the referrer for same-origin
|
||||||
|
links, and only the origin for cross-origin links.
|
||||||
|
|
||||||
|
``same-origin``
|
||||||
|
Instructs the browser to send a full URL, but only for same-origin links. No
|
||||||
|
referrer will be sent for cross-origin links.
|
||||||
|
|
||||||
|
``strict-origin``
|
||||||
|
Instructs the browser to send only the origin, not the full URL, and to send
|
||||||
|
no referrer when a protocol downgrade occurs.
|
||||||
|
|
||||||
|
``strict-origin-when-cross-origin``
|
||||||
|
Instructs the browser to send the full URL when the link is same-origin and
|
||||||
|
no protocol downgrade occurs; send only the origin when the link is
|
||||||
|
cross-origin and no protocol downgrade occurs; and no referrer when a
|
||||||
|
protocol downgrade occurs.
|
||||||
|
|
||||||
|
``unsafe-url``
|
||||||
|
Instructs the browser to always send the full URL as the referrer.
|
||||||
|
|
||||||
|
.. admonition:: Unknown Policy Values
|
||||||
|
|
||||||
|
Where a policy value is `unknown`__ by a user agent, it is possible to
|
||||||
|
specify multiple policy values to provide a fallback. The last specified
|
||||||
|
value that is understood takes precedence. To support this, an iterable or
|
||||||
|
comma-separated string can be used with :setting:`SECURE_REFERRER_POLICY`.
|
||||||
|
|
||||||
|
__ https://w3c.github.io/webappsec-referrer-policy/#unknown-policy-values
|
||||||
|
|
||||||
.. _x-content-type-options:
|
.. _x-content-type-options:
|
||||||
|
|
||||||
``X-Content-Type-Options: nosniff``
|
``X-Content-Type-Options: nosniff``
|
||||||
|
|
|
@ -2319,6 +2319,19 @@ If a URL path matches a regular expression in this list, the request will not be
|
||||||
redirected to HTTPS. If :setting:`SECURE_SSL_REDIRECT` is ``False``, this
|
redirected to HTTPS. If :setting:`SECURE_SSL_REDIRECT` is ``False``, this
|
||||||
setting has no effect.
|
setting has no effect.
|
||||||
|
|
||||||
|
.. setting:: SECURE_REFERRER_POLICY
|
||||||
|
|
||||||
|
``SECURE_REFERRER_POLICY``
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
.. versionadded:: 3.0
|
||||||
|
|
||||||
|
Default: ``None``
|
||||||
|
|
||||||
|
If configured, the :class:`~django.middleware.security.SecurityMiddleware` sets
|
||||||
|
the :ref:`referrer-policy` header on all responses that do not already have it
|
||||||
|
to the value provided.
|
||||||
|
|
||||||
.. setting:: SECURE_SSL_HOST
|
.. setting:: SECURE_SSL_HOST
|
||||||
|
|
||||||
``SECURE_SSL_HOST``
|
``SECURE_SSL_HOST``
|
||||||
|
@ -3500,6 +3513,7 @@ HTTP
|
||||||
* :setting:`SECURE_HSTS_SECONDS`
|
* :setting:`SECURE_HSTS_SECONDS`
|
||||||
* :setting:`SECURE_PROXY_SSL_HEADER`
|
* :setting:`SECURE_PROXY_SSL_HEADER`
|
||||||
* :setting:`SECURE_REDIRECT_EXEMPT`
|
* :setting:`SECURE_REDIRECT_EXEMPT`
|
||||||
|
* :setting:`SECURE_REFERRER_POLICY`
|
||||||
* :setting:`SECURE_SSL_HOST`
|
* :setting:`SECURE_SSL_HOST`
|
||||||
* :setting:`SECURE_SSL_REDIRECT`
|
* :setting:`SECURE_SSL_REDIRECT`
|
||||||
* :setting:`SIGNING_BACKEND`
|
* :setting:`SIGNING_BACKEND`
|
||||||
|
|
|
@ -380,6 +380,9 @@ Security
|
||||||
:ref:`x-content-type-options` header on all responses that do not already
|
:ref:`x-content-type-options` header on all responses that do not already
|
||||||
have it.
|
have it.
|
||||||
|
|
||||||
|
* :class:`~django.middleware.security.SecurityMiddleware` can now send the
|
||||||
|
:ref:`Referrer-Policy <referrer-policy>` header.
|
||||||
|
|
||||||
Serialization
|
Serialization
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -204,6 +204,15 @@ Additionally, Django requires you to explicitly enable support for the
|
||||||
``X-Forwarded-Host`` header (via the :setting:`USE_X_FORWARDED_HOST` setting)
|
``X-Forwarded-Host`` header (via the :setting:`USE_X_FORWARDED_HOST` setting)
|
||||||
if your configuration requires it.
|
if your configuration requires it.
|
||||||
|
|
||||||
|
Referrer policy
|
||||||
|
===============
|
||||||
|
|
||||||
|
Browsers use the ``Referer`` header as a way to send information to a site
|
||||||
|
about how users got there. By setting a *Referrer Policy* you can help to
|
||||||
|
protect the privacy of your users, restricting under which circumstances the
|
||||||
|
``Referer`` header is set. See :ref:`the referrer policy section of the
|
||||||
|
security middleware reference <referrer-policy>` for details.
|
||||||
|
|
||||||
Session security
|
Session security
|
||||||
================
|
================
|
||||||
|
|
||||||
|
|
|
@ -502,3 +502,46 @@ class CheckAllowedHostsTest(SimpleTestCase):
|
||||||
@override_settings(ALLOWED_HOSTS=['.example.com'])
|
@override_settings(ALLOWED_HOSTS=['.example.com'])
|
||||||
def test_allowed_hosts_set(self):
|
def test_allowed_hosts_set(self):
|
||||||
self.assertEqual(self.func(None), [])
|
self.assertEqual(self.func(None), [])
|
||||||
|
|
||||||
|
|
||||||
|
class CheckReferrerPolicyTest(SimpleTestCase):
|
||||||
|
|
||||||
|
@property
|
||||||
|
def func(self):
|
||||||
|
from django.core.checks.security.base import check_referrer_policy
|
||||||
|
return check_referrer_policy
|
||||||
|
|
||||||
|
@override_settings(
|
||||||
|
MIDDLEWARE=['django.middleware.security.SecurityMiddleware'],
|
||||||
|
SECURE_REFERRER_POLICY=None,
|
||||||
|
)
|
||||||
|
def test_no_referrer_policy(self):
|
||||||
|
self.assertEqual(self.func(None), [base.W022])
|
||||||
|
|
||||||
|
@override_settings(MIDDLEWARE=[], SECURE_REFERRER_POLICY=None)
|
||||||
|
def test_no_referrer_policy_no_middleware(self):
|
||||||
|
"""
|
||||||
|
Don't warn if SECURE_REFERRER_POLICY is None and SecurityMiddleware
|
||||||
|
isn't in MIDDLEWARE.
|
||||||
|
"""
|
||||||
|
self.assertEqual(self.func(None), [])
|
||||||
|
|
||||||
|
@override_settings(MIDDLEWARE=['django.middleware.security.SecurityMiddleware'])
|
||||||
|
def test_with_referrer_policy(self):
|
||||||
|
tests = (
|
||||||
|
'strict-origin',
|
||||||
|
'strict-origin,origin',
|
||||||
|
'strict-origin, origin',
|
||||||
|
['strict-origin', 'origin'],
|
||||||
|
('strict-origin', 'origin'),
|
||||||
|
)
|
||||||
|
for value in tests:
|
||||||
|
with self.subTest(value=value), override_settings(SECURE_REFERRER_POLICY=value):
|
||||||
|
self.assertEqual(self.func(None), [])
|
||||||
|
|
||||||
|
@override_settings(
|
||||||
|
MIDDLEWARE=['django.middleware.security.SecurityMiddleware'],
|
||||||
|
SECURE_REFERRER_POLICY='invalid-value',
|
||||||
|
)
|
||||||
|
def test_with_invalid_referrer_policy(self):
|
||||||
|
self.assertEqual(self.func(None), [base.E023])
|
||||||
|
|
|
@ -222,3 +222,36 @@ class SecurityMiddlewareTest(SimpleTestCase):
|
||||||
"""
|
"""
|
||||||
ret = self.process_request("get", "/some/url")
|
ret = self.process_request("get", "/some/url")
|
||||||
self.assertIsNone(ret)
|
self.assertIsNone(ret)
|
||||||
|
|
||||||
|
@override_settings(SECURE_REFERRER_POLICY=None)
|
||||||
|
def test_referrer_policy_off(self):
|
||||||
|
"""
|
||||||
|
With SECURE_REFERRER_POLICY set to None, the middleware does not add a
|
||||||
|
"Referrer-Policy" header to the response.
|
||||||
|
"""
|
||||||
|
self.assertNotIn('Referrer-Policy', self.process_response())
|
||||||
|
|
||||||
|
def test_referrer_policy_on(self):
|
||||||
|
"""
|
||||||
|
With SECURE_REFERRER_POLICY set to a valid value, the middleware adds a
|
||||||
|
"Referrer-Policy" header to the response.
|
||||||
|
"""
|
||||||
|
tests = (
|
||||||
|
('strict-origin', 'strict-origin'),
|
||||||
|
('strict-origin,origin', 'strict-origin,origin'),
|
||||||
|
('strict-origin, origin', 'strict-origin,origin'),
|
||||||
|
(['strict-origin', 'origin'], 'strict-origin,origin'),
|
||||||
|
(('strict-origin', 'origin'), 'strict-origin,origin'),
|
||||||
|
)
|
||||||
|
for value, expected in tests:
|
||||||
|
with self.subTest(value=value), override_settings(SECURE_REFERRER_POLICY=value):
|
||||||
|
self.assertEqual(self.process_response()['Referrer-Policy'], expected)
|
||||||
|
|
||||||
|
@override_settings(SECURE_REFERRER_POLICY='strict-origin')
|
||||||
|
def test_referrer_policy_already_present(self):
|
||||||
|
"""
|
||||||
|
The middleware will not override a "Referrer-Policy" header already
|
||||||
|
present in the response.
|
||||||
|
"""
|
||||||
|
response = self.process_response(headers={'Referrer-Policy': 'unsafe-url'})
|
||||||
|
self.assertEqual(response['Referrer-Policy'], 'unsafe-url')
|
||||||
|
|
Loading…
Reference in New Issue