summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEd Morley <emorley@mozilla.com>2016-07-28 17:48:07 +0100
committerTim Graham <timograham@gmail.com>2016-08-10 20:23:54 -0400
commit3c2447dd13e495d57700ca8447896acd85044444 (patch)
tree26ad18a7df9ff5b0d9e35723164baa4587747e4b
parentc412aaca735c7cc1c766b85c1512f9ff434ce63a (diff)
Fixed #26947 -- Added an option to enable the HSTS header preload directive.
-rw-r--r--django/conf/global_settings.py1
-rw-r--r--django/middleware/security.py5
-rw-r--r--docs/ref/middleware.txt6
-rw-r--r--docs/ref/settings.txt20
-rw-r--r--docs/releases/1.11.txt3
-rw-r--r--docs/topics/security.txt5
-rw-r--r--tests/middleware/test_security.py31
7 files changed, 67 insertions, 4 deletions
diff --git a/django/conf/global_settings.py b/django/conf/global_settings.py
index 94cfcf25e5..a745b9cc4d 100644
--- a/django/conf/global_settings.py
+++ b/django/conf/global_settings.py
@@ -629,6 +629,7 @@ SILENCED_SYSTEM_CHECKS = []
SECURE_BROWSER_XSS_FILTER = False
SECURE_CONTENT_TYPE_NOSNIFF = False
SECURE_HSTS_INCLUDE_SUBDOMAINS = False
+SECURE_HSTS_PRELOAD = False
SECURE_HSTS_SECONDS = 0
SECURE_REDIRECT_EXEMPT = []
SECURE_SSL_HOST = None
diff --git a/django/middleware/security.py b/django/middleware/security.py
index 02a59ad6e4..7bcb72738e 100644
--- a/django/middleware/security.py
+++ b/django/middleware/security.py
@@ -9,6 +9,7 @@ class SecurityMiddleware(MiddlewareMixin):
def __init__(self, get_response=None):
self.sts_seconds = settings.SECURE_HSTS_SECONDS
self.sts_include_subdomains = settings.SECURE_HSTS_INCLUDE_SUBDOMAINS
+ self.sts_preload = settings.SECURE_HSTS_PRELOAD
self.content_type_nosniff = settings.SECURE_CONTENT_TYPE_NOSNIFF
self.xss_filter = settings.SECURE_BROWSER_XSS_FILTER
self.redirect = settings.SECURE_SSL_REDIRECT
@@ -30,10 +31,10 @@ class SecurityMiddleware(MiddlewareMixin):
if (self.sts_seconds and request.is_secure() and
'strict-transport-security' not in response):
sts_header = "max-age=%s" % self.sts_seconds
-
if self.sts_include_subdomains:
sts_header = sts_header + "; includeSubDomains"
-
+ if self.sts_preload:
+ sts_header = sts_header + "; preload"
response["strict-transport-security"] = sts_header
if self.content_type_nosniff and 'x-content-type-options' not in response:
diff --git a/docs/ref/middleware.txt b/docs/ref/middleware.txt
index cee18ea058..8334c44216 100644
--- a/docs/ref/middleware.txt
+++ b/docs/ref/middleware.txt
@@ -226,6 +226,7 @@ enabled or disabled with a setting.
* :setting:`SECURE_BROWSER_XSS_FILTER`
* :setting:`SECURE_CONTENT_TYPE_NOSNIFF`
* :setting:`SECURE_HSTS_INCLUDE_SUBDOMAINS`
+* :setting:`SECURE_HSTS_PRELOAD`
* :setting:`SECURE_HSTS_SECONDS`
* :setting:`SECURE_REDIRECT_EXEMPT`
* :setting:`SECURE_SSL_HOST`
@@ -260,6 +261,10 @@ to the ``Strict-Transport-Security`` header. This is recommended (assuming all
subdomains are served exclusively using HTTPS), otherwise your site may still
be vulnerable via an insecure connection to a subdomain.
+If you wish to submit your site to the `browser preload list`_, set the
+:setting:`SECURE_HSTS_PRELOAD` setting to ``True``. That appends the
+``preload`` directive to the ``Strict-Transport-Security`` header.
+
.. warning::
The HSTS policy applies to your entire domain, not just the URL of the
response that you set the header on. Therefore, you should only use it if
@@ -277,6 +282,7 @@ be vulnerable via an insecure connection to a subdomain.
you may need to set the :setting:`SECURE_PROXY_SSL_HEADER` setting.
.. _"Strict-Transport-Security" header: https://en.wikipedia.org/wiki/Strict_Transport_Security
+.. _browser preload list: https://hstspreload.appspot.com/
.. _x-content-type-options:
diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt
index 9e0d8b8d41..445e504e98 100644
--- a/docs/ref/settings.txt
+++ b/docs/ref/settings.txt
@@ -2062,6 +2062,25 @@ non-zero value.
:setting:`SECURE_HSTS_SECONDS`) break your site. Read the
:ref:`http-strict-transport-security` documentation first.
+.. setting:: SECURE_HSTS_PRELOAD
+
+``SECURE_HSTS_PRELOAD``
+-----------------------
+
+.. versionadded:: 1.11
+
+Default: ``False``
+
+If ``True``, the :class:`~django.middleware.security.SecurityMiddleware` adds
+the ``preload`` directive to the :ref:`http-strict-transport-security`
+header. It has no effect unless :setting:`SECURE_HSTS_SECONDS` is set to a
+non-zero value.
+
+.. warning::
+ Setting this incorrectly can irreversibly (for at least several months,
+ depending on browser releases) break your site. Read the
+ :ref:`http-strict-transport-security` documentation first.
+
.. setting:: SECURE_HSTS_SECONDS
``SECURE_HSTS_SECONDS``
@@ -3334,6 +3353,7 @@ HTTP
* :setting:`SECURE_BROWSER_XSS_FILTER`
* :setting:`SECURE_CONTENT_TYPE_NOSNIFF`
* :setting:`SECURE_HSTS_INCLUDE_SUBDOMAINS`
+ * :setting:`SECURE_HSTS_PRELOAD`
* :setting:`SECURE_HSTS_SECONDS`
* :setting:`SECURE_PROXY_SSL_HEADER`
* :setting:`SECURE_REDIRECT_EXEMPT`
diff --git a/docs/releases/1.11.txt b/docs/releases/1.11.txt
index d8534c0d11..64a5fc2780 100644
--- a/docs/releases/1.11.txt
+++ b/docs/releases/1.11.txt
@@ -229,6 +229,9 @@ Requests and Responses
* :class:`~django.middleware.common.CommonMiddleware` now sets the
``Content-Length`` response header for non-streaming responses.
+* Added the :setting:`SECURE_HSTS_PRELOAD` setting to allow appending the
+ ``preload`` directive to the ``Strict-Transport-Security`` header.
+
Serialization
~~~~~~~~~~~~~
diff --git a/docs/topics/security.txt b/docs/topics/security.txt
index ff33e8be6d..8d7b9c91f1 100644
--- a/docs/topics/security.txt
+++ b/docs/topics/security.txt
@@ -160,8 +160,9 @@ server, there are some additional steps you may need:
to a particular site should always use HTTPS. Combined with redirecting
requests over HTTP to HTTPS, this will ensure that connections always enjoy
the added security of SSL provided one successful connection has occurred.
- HSTS may either be configured with :setting:`SECURE_HSTS_SECONDS` and
- :setting:`SECURE_HSTS_INCLUDE_SUBDOMAINS` or on the Web server.
+ HSTS may either be configured with :setting:`SECURE_HSTS_SECONDS`,
+ :setting:`SECURE_HSTS_INCLUDE_SUBDOMAINS`, and :setting:`SECURE_HSTS_PRELOAD`,
+ or on the Web server.
.. _host-headers-virtual-hosting:
diff --git a/tests/middleware/test_security.py b/tests/middleware/test_security.py
index f671600c49..b8e77f76e4 100644
--- a/tests/middleware/test_security.py
+++ b/tests/middleware/test_security.py
@@ -99,6 +99,37 @@ class SecurityMiddlewareTest(SimpleTestCase):
response = self.process_response(secure=True)
self.assertEqual(response["strict-transport-security"], "max-age=600")
+ @override_settings(SECURE_HSTS_SECONDS=10886400, SECURE_HSTS_PRELOAD=True)
+ def test_sts_preload(self):
+ """
+ With HSTS_SECONDS non-zero and SECURE_HSTS_PRELOAD True, the middleware
+ adds a "strict-transport-security" header with the "preload" directive
+ to the response.
+ """
+ response = self.process_response(secure=True)
+ self.assertEqual(response["strict-transport-security"], "max-age=10886400; preload")
+
+ @override_settings(SECURE_HSTS_SECONDS=10886400, SECURE_HSTS_INCLUDE_SUBDOMAINS=True, SECURE_HSTS_PRELOAD=True)
+ def test_sts_subdomains_and_preload(self):
+ """
+ With HSTS_SECONDS non-zero, SECURE_HSTS_INCLUDE_SUBDOMAINS and
+ SECURE_HSTS_PRELOAD True, the middleware adds a "strict-transport-security"
+ header containing both the "includeSubDomains" and "preload" directives
+ to the response.
+ """
+ response = self.process_response(secure=True)
+ self.assertEqual(response["strict-transport-security"], "max-age=10886400; includeSubDomains; preload")
+
+ @override_settings(SECURE_HSTS_SECONDS=10886400, SECURE_HSTS_PRELOAD=False)
+ def test_sts_no_preload(self):
+ """
+ With HSTS_SECONDS non-zero and SECURE_HSTS_PRELOAD
+ False, the middleware adds a "strict-transport-security" header without
+ the "preload" directive to the response.
+ """
+ response = self.process_response(secure=True)
+ self.assertEqual(response["strict-transport-security"], "max-age=10886400")
+
@override_settings(SECURE_CONTENT_TYPE_NOSNIFF=True)
def test_content_type_on(self):
"""