From 1bfa20d7a95efced619554335e1906d2d28971c3 Mon Sep 17 00:00:00 2001 From: Sage Abdullah Date: Fri, 28 Oct 2022 12:58:58 +0100 Subject: [PATCH] Add configurable Content-Security-Policy headers --- apps/guide/settings/base.py | 24 ++++++++++++++++++++++++ poetry.lock | 21 ++++++++++++++++++++- pyproject.toml | 1 + setup.cfg | 3 ++- 4 files changed, 47 insertions(+), 2 deletions(-) diff --git a/apps/guide/settings/base.py b/apps/guide/settings/base.py index 6ce0c3dc..12a34cf5 100644 --- a/apps/guide/settings/base.py +++ b/apps/guide/settings/base.py @@ -206,6 +206,30 @@ "usb": [], } +# Content Security policy settings +# http://django-csp.readthedocs.io/en/latest/configuration.html +if "CSP_DEFAULT_SRC" in env: + MIDDLEWARE.append("csp.middleware.CSPMiddleware") + + # The “special” source values of + # 'self', 'unsafe-inline', 'unsafe-eval', and 'none' must be quoted! + # e.g.: CSP_DEFAULT_SRC = "'self'" Without quotes they will not work as intended. + + CSP_DEFAULT_SRC = env.get("CSP_DEFAULT_SRC").split(",") + if "CSP_SCRIPT_SRC" in env: + CSP_SCRIPT_SRC = env.get("CSP_SCRIPT_SRC").split(",") + if "CSP_STYLE_SRC" in env: + CSP_STYLE_SRC = env.get("CSP_STYLE_SRC").split(",") + if "CSP_IMG_SRC" in env: + CSP_IMG_SRC = env.get("CSP_IMG_SRC").split(",") + if "CSP_CONNECT_SRC" in env: + CSP_CONNECT_SRC = env.get("CSP_CONNECT_SRC").split(",") + if "CSP_FONT_SRC" in env: + CSP_FONT_SRC = env.get("CSP_FONT_SRC").split(",") + if "CSP_BASE_URI" in env: + CSP_BASE_URI = env.get("CSP_BASE_URI").split(",") + if "CSP_OBJECT_SRC" in env: + CSP_OBJECT_SRC = env.get("CSP_OBJECT_SRC").split(",") # Internationalization # https://docs.djangoproject.com/en/4.0/topics/i18n/ diff --git a/poetry.lock b/poetry.lock index c5bc2300..a7b2618a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -199,6 +199,21 @@ Django = ">=1.8,<5" [package.extras] lint = ["black (==20.8b1)", "flake8 (==3.8.4)", "isort (==5.7.0)"] +[[package]] +name = "django-csp" +version = "3.7" +description = "Django Content Security Policy support." +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +Django = ">=1.8" + +[package.extras] +jinja2 = ["jinja2 (>=2.9.6)"] +tests = ["jinja2 (>=2.9.6)", "mock (==1.0.1)", "pep8 (==1.4.6)", "pytest (<4.0)", "pytest-django", "pytest-flakes (==1.0.1)", "pytest-pep8 (==1.0.6)", "six (==1.12.0)"] + [[package]] name = "django-extensions" version = "3.2.1" @@ -952,7 +967,7 @@ python-versions = "*" [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "826f01e4e312255ac6c42504a480babbb9f80b9d104a6fb3cbb52afc377a4e4f" +content-hash = "6929f9157349e3454bc992f39983a7a3f4f137d4b2f23c21981d54e34101d018" [metadata.files] anyascii = [ @@ -1086,6 +1101,10 @@ django-basic-auth-ip-whitelist = [ {file = "django-basic-auth-ip-whitelist-0.5a0.tar.gz", hash = "sha256:06c2e3800d492781d88aeafdb57e418e30354cb0dbbfc01ac3ce59f67f50d31a"}, {file = "django_basic_auth_ip_whitelist-0.5a0-py3-none-any.whl", hash = "sha256:047bafc88c69f5aace60ca4a262d7e6e56f9767196e31623025743b08265ed22"}, ] +django-csp = [ + {file = "django_csp-3.7-py2.py3-none-any.whl", hash = "sha256:01443a07723f9a479d498bd7bb63571aaa771e690f64bde515db6cdb76e8041a"}, + {file = "django_csp-3.7.tar.gz", hash = "sha256:01eda02ad3f10261c74131cdc0b5a6a62b7c7ad4fd017fbefb7a14776e0a9727"}, +] django-extensions = [ {file = "django-extensions-3.2.1.tar.gz", hash = "sha256:2a4f4d757be2563cd1ff7cfdf2e57468f5f931cc88b23cf82ca75717aae504a4"}, {file = "django_extensions-3.2.1-py3-none-any.whl", hash = "sha256:421464be390289513f86cb5e18eb43e5dc1de8b4c27ba9faa3b91261b0d67e09"}, diff --git a/pyproject.toml b/pyproject.toml index 702bd7cb..5aff82a3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,6 +21,7 @@ whitenoise = "6.2.0" psycopg2 = "2.9.3" wagtail-localize = "^1.3.1" django-permissions-policy = "^4.13.0" +django-csp = "^3.7" [tool.poetry.group.dev.dependencies] black = "^22.10.0" diff --git a/setup.cfg b/setup.cfg index b9726d41..c7ab7184 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,4 +1,5 @@ [flake8] +ignore = C901,W503 max-line-length = 88 max-complexity = 8 exclude = */migrations/* @@ -22,4 +23,4 @@ omit = *migrations* [coverage:report] -show_missing = True \ No newline at end of file +show_missing = True