summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--django/core/checks/security/base.py16
-rw-r--r--docs/ref/checks.txt3
-rw-r--r--docs/spelling_wordlist1
-rw-r--r--tests/check_framework/test_security.py44
4 files changed, 64 insertions, 0 deletions
diff --git a/django/core/checks/security/base.py b/django/core/checks/security/base.py
index eee7f854c8..f482f77153 100644
--- a/django/core/checks/security/base.py
+++ b/django/core/checks/security/base.py
@@ -101,6 +101,12 @@ W020 = Warning(
id='security.W020',
)
+W021 = Warning(
+ "You have not set the SECURE_HSTS_PRELOAD setting to True. Without this, "
+ "your site cannot be submitted to the browser preload list.",
+ id='security.W021',
+)
+
def _security_middleware():
return ("django.middleware.security.SecurityMiddleware" in settings.MIDDLEWARE_CLASSES or
@@ -141,6 +147,16 @@ def check_sts_include_subdomains(app_configs, **kwargs):
@register(Tags.security, deploy=True)
+def check_sts_preload(app_configs, **kwargs):
+ passed_check = (
+ not _security_middleware() or
+ not settings.SECURE_HSTS_SECONDS or
+ settings.SECURE_HSTS_PRELOAD is True
+ )
+ return [] if passed_check else [W021]
+
+
+@register(Tags.security, deploy=True)
def check_content_type_nosniff(app_configs, **kwargs):
passed_check = (
not _security_middleware() or
diff --git a/docs/ref/checks.txt b/docs/ref/checks.txt
index 5eed9f0aed..e0c24eb07d 100644
--- a/docs/ref/checks.txt
+++ b/docs/ref/checks.txt
@@ -596,6 +596,9 @@ The following checks are run if you use the :option:`check --deploy` option:
for your site to serve other parts of itself in a frame, you should change
it to ``'DENY'``.
* **security.W020**: :setting:`ALLOWED_HOSTS` must not be empty in deployment.
+* **security.W021**: You have not set the
+ :setting:`SECURE_HSTS_PRELOAD` setting to ``True``. Without this, your site
+ cannot be submitted to the browser preload list.
Sites
-----
diff --git a/docs/spelling_wordlist b/docs/spelling_wordlist
index 5a935d30e1..7712c4c02e 100644
--- a/docs/spelling_wordlist
+++ b/docs/spelling_wordlist
@@ -594,6 +594,7 @@ prefetches
prefetching
prefork
preforked
+preload
prepend
prepended
prepending
diff --git a/tests/check_framework/test_security.py b/tests/check_framework/test_security.py
index b4591030f5..ebd1ffb0d3 100644
--- a/tests/check_framework/test_security.py
+++ b/tests/check_framework/test_security.py
@@ -307,6 +307,50 @@ class CheckStrictTransportSecuritySubdomainsTest(SimpleTestCase):
self.assertEqual(self.func(None), [])
+class CheckStrictTransportSecurityPreloadTest(SimpleTestCase):
+ @property
+ def func(self):
+ from django.core.checks.security.base import check_sts_preload
+ return check_sts_preload
+
+ @override_settings(
+ MIDDLEWARE=["django.middleware.security.SecurityMiddleware"],
+ SECURE_HSTS_PRELOAD=False,
+ SECURE_HSTS_SECONDS=3600,
+ )
+ def test_no_sts_preload(self):
+ """
+ Warn if SECURE_HSTS_PRELOAD isn't True.
+ """
+ self.assertEqual(self.func(None), [base.W021])
+
+ @override_settings(MIDDLEWARE=[], SECURE_HSTS_PRELOAD=False, SECURE_HSTS_SECONDS=3600)
+ def test_no_sts_preload_no_middleware(self):
+ """
+ Don't warn if SecurityMiddleware isn't installed.
+ """
+ self.assertEqual(self.func(None), [])
+
+ @override_settings(
+ MIDDLEWARE=["django.middleware.security.SecurityMiddleware"],
+ SECURE_SSL_REDIRECT=False,
+ SECURE_HSTS_SECONDS=None,
+ )
+ def test_no_sts_preload_no_seconds(self):
+ """
+ Don't warn if SECURE_HSTS_SECONDS isn't set.
+ """
+ self.assertEqual(self.func(None), [])
+
+ @override_settings(
+ MIDDLEWARE=["django.middleware.security.SecurityMiddleware"],
+ SECURE_HSTS_PRELOAD=True,
+ SECURE_HSTS_SECONDS=3600,
+ )
+ def test_with_sts_preload(self):
+ self.assertEqual(self.func(None), [])
+
+
class CheckXFrameOptionsMiddlewareTest(SimpleTestCase):
@property
def func(self):