1
0
mirror of https://github.com/django/django.git synced 2025-10-24 22:26:08 +00:00

Fixed #15727 -- Added Content Security Policy (CSP) support.

This initial work adds a pair of settings to configure specific CSP
directives for enforcing or reporting policy violations, a new
`django.middleware.csp.ContentSecurityPolicyMiddleware` to apply the
appropriate headers to responses, and a context processor to support CSP
nonces in templates for safely inlining assets.

Relevant documentation has been added for the 6.0 release notes,
security overview, a new how-to page, and a dedicated reference section.

Thanks to the multiple reviewers for their precise and valuable feedback.

Co-authored-by: Natalia <124304+nessita@users.noreply.github.com>
This commit is contained in:
Rob Hudson
2025-05-03 10:01:58 -07:00
committed by nessita
parent 3f59711581
commit d63241ebc7
26 changed files with 1192 additions and 1 deletions

View File

@@ -1,3 +1,5 @@
import itertools
from django.conf import settings
from django.core.checks.messages import Error, Warning
from django.core.checks.security import base, csrf, sessions
@@ -678,3 +680,54 @@ class CheckCrossOriginOpenerPolicyTest(SimpleTestCase):
)
def test_with_invalid_coop(self):
self.assertEqual(base.check_cross_origin_opener_policy(None), [base.E024])
class CheckSecureCSPTests(SimpleTestCase):
"""Tests for the CSP settings check function."""
def test_secure_csp_allowed_values(self):
"""Check should pass when both CSP settings are None or dicts."""
allowed_values = (None, {}, {"key": "value"})
combinations = itertools.product(allowed_values, repeat=2)
for csp_value, csp_report_only_value in combinations:
with (
self.subTest(
csp_value=csp_value, csp_report_only_value=csp_report_only_value
),
self.settings(
SECURE_CSP=csp_value, SECURE_CSP_REPORT_ONLY=csp_report_only_value
),
):
errors = base.check_csp_settings(None)
self.assertEqual(errors, [])
def test_secure_csp_invalid_values(self):
"""Check should fail when either CSP setting is not a dict."""
for value in (
False,
True,
0,
42,
"",
"not-a-dict",
set(),
{"a", "b"},
[],
[1, 2, 3, 4],
):
with self.subTest(value=value):
csp_error = Error(
base.E026.msg % ("SECURE_CSP", value), id=base.E026.id
)
with self.settings(SECURE_CSP=value):
errors = base.check_csp_settings(None)
self.assertEqual(errors, [csp_error])
csp_report_only_error = Error(
base.E026.msg % ("SECURE_CSP_REPORT_ONLY", value), id=base.E026.id
)
with self.settings(SECURE_CSP_REPORT_ONLY=value):
errors = base.check_csp_settings(None)
self.assertEqual(errors, [csp_report_only_error])
with self.settings(SECURE_CSP=value, SECURE_CSP_REPORT_ONLY=value):
errors = base.check_csp_settings(None)
self.assertEqual(errors, [csp_error, csp_report_only_error])