#37441 closed Uncategorized (duplicate)

Silently dropped CSP directive when nonce sentinel is the only value

Reported by: Ariel Poghon Owned by: Ariel Poghon
Component: HTTP handling Version: 6.1
Severity: Normal Keywords: csp, nonce, security
Cc: Triage Stage: Unreviewed
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: yes UI/UX: no

Description

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).

Change History (2)

comment:1 by Ariel Poghon, 35 minutes ago

Owner: set to Ariel Poghon
Status: new → assigned

Submitted PR #22178

comment:2 by Sarah Boyce, 11 minutes ago

Resolution: → duplicate
Status: assigned → closed

Duplicate of #37395, feel free to discuss potential solutions in that ticket

Note: See TracTickets for help on using tickets.
Back to Top