﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
37441	Silently dropped CSP directive when nonce sentinel is the only value	Ariel Poghon	Ariel Poghon	"django.utils.csp.build_policy() removes CSP.NONCE placeholders when the nonce is
never generated for the request (the nonce is created lazily, only when something
accesses it, e.g. the csp_nonce template context key). Current code:

    values = [v for v in values if v != CSP.NONCE]

followed by an empty-value guard that skips the directive. When the sentinel is
the **only** value of a directive, `values` becomes empty and the directive is
dropped entirely.

With

    SECURE_CSP = {
        ""default-src"": [""'self'""],
        ""script-src"": [CSP.NONCE],
    }

a response that never evaluates the nonce ships:

    Content-Security-Policy: default-src 'self';

... `script-src` silently disappears, and the nonce-only intent (only
nonce-bearing scripts may run) degrades to a weaker effective policy. A
sentinel-only `SECURE_CSP` produces no CSP header at all (fail-open).

Minimal repro on 6.1:
    from django.utils.csp import build_policy, CSP
    build_policy({""script-src"": CSP.NONCE}, nonce=None)  # => """"

PR (has patch attached here):
https://github.com/django/django/pull/22178

Fix: substitute 'none' when the sentinel is removed and was the sole value, keeping the
directive present and restrictive (""script-src 'none'""). 'none' rather than an empty
value avoids inconsistent browser handling of empty source lists. Two tests added
(tests/utils_tests/test_csp.py); full CSP-related suites pass locally (74 tests, 0
failures)."	Uncategorized	closed	HTTP handling	6.1	Normal	duplicate	csp,nonce,security		Unreviewed	1	0	0	0	1	0
