From d9c6bad5bae397abd48547028c6f0beffb5d90a1 Mon Sep 17 00:00:00 2001 From: Andy Mitchell <326561+Themitchell@users.noreply.github.com> Date: Tue, 10 Mar 2026 12:37:34 +0000 Subject: [PATCH 1/2] PPHA-682: Add strict Content Security Policy --- lung_cancer_screening/settings.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/lung_cancer_screening/settings.py b/lung_cancer_screening/settings.py index 95af47d4..6f3c2760 100644 --- a/lung_cancer_screening/settings.py +++ b/lung_cancer_screening/settings.py @@ -12,6 +12,7 @@ import sys from os import environ from pathlib import Path +from django.utils.csp import CSP from jinja2 import ChainableUndefined @@ -73,15 +74,16 @@ def pem_key_env(key, file_path_key=None): ] MIDDLEWARE = [ - 'django.middleware.security.SecurityMiddleware', + "django.middleware.security.SecurityMiddleware", "whitenoise.middleware.WhiteNoiseMiddleware", - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', + "django.contrib.sessions.middleware.SessionMiddleware", + "django.middleware.common.CommonMiddleware", + "django.middleware.csrf.CsrfViewMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", "lung_cancer_screening.questions.middleware.session_timeout.SessionTimeoutMiddleware", - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', + "django.contrib.messages.middleware.MessageMiddleware", + "django.middleware.clickjacking.XFrameOptionsMiddleware", + "django.middleware.csp.ContentSecurityPolicyMiddleware", ] ROOT_URLCONF = 'lung_cancer_screening.urls' @@ -284,3 +286,9 @@ def pem_key_env(key, file_path_key=None): DISABLE_RECENT_SUBMISSION_LIMITATION = boolean_env("DISABLE_RECENT_SUBMISSION_LIMITATION", default=False) COMMIT_SHA = environ.get("COMMIT_SHA", "unknown") + +SECURE_CSP = { + "default-src": [CSP.SELF], + "font-src": (CSP.SELF, "https://assets.nhs.uk"), + "script-src": (CSP.SELF, "'unsafe-inline'"), +} From 71355d57d0fd99b29339b8b64556b8a5f6ea0ac1 Mon Sep 17 00:00:00 2001 From: Andy Mitchell <326561+Themitchell@users.noreply.github.com> Date: Tue, 10 Mar 2026 12:46:06 +0000 Subject: [PATCH 2/2] PPHA-682: Add HSTS settings --- lung_cancer_screening/settings.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/lung_cancer_screening/settings.py b/lung_cancer_screening/settings.py index 6f3c2760..2b70f21e 100644 --- a/lung_cancer_screening/settings.py +++ b/lung_cancer_screening/settings.py @@ -276,13 +276,6 @@ def pem_key_env(key, file_path_key=None): LOGIN_REDIRECT_URL_FAILURE = "/agree-to-share-information" ALLOW_LOGOUT_GET_METHOD = True -# Additional security settings for production -if not DEBUG: - SECURE_SSL_REDIRECT = False - SESSION_COOKIE_SECURE = True - CSRF_COOKIE_SECURE = True - USE_X_FORWARDED_HOST = True - DISABLE_RECENT_SUBMISSION_LIMITATION = boolean_env("DISABLE_RECENT_SUBMISSION_LIMITATION", default=False) COMMIT_SHA = environ.get("COMMIT_SHA", "unknown") @@ -292,3 +285,12 @@ def pem_key_env(key, file_path_key=None): "font-src": (CSP.SELF, "https://assets.nhs.uk"), "script-src": (CSP.SELF, "'unsafe-inline'"), } + +# Additional security settings for production +if not DEBUG: + SECURE_HSTS_SECONDS = 31536000 + SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") + SECURE_SSL_REDIRECT = False + SESSION_COOKIE_SECURE = True + CSRF_COOKIE_SECURE = True + USE_X_FORWARDED_HOST = True