#37395 new New feature

Add a system check for a CSP directive whose only source is CSP.NONCE (silently fails open)

Reported by: venkatchalla06 Owned by:
Component: Core (System checks) Version: dev
Severity: Normal Keywords:
Cc: venkatchalla06 Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Django 6.0 added built-in CSP. In django.utils.csp.build_policy(), when a directive's only source is CSP.NONCE and the per-request nonce was never accessed (the LazyNonce stays falsy because the response rendered no {{ csp_nonce }}), the sentinel is stripped, the directive becomes empty, and the directive is dropped from the header entirely. For the same configuration, the emitted policy then depends on whether the nonce happened to be used:

  • {"default-src": ["*"], "script-src": [CSP.NONCE]} — nonce used: default-src *; script-src 'nonce-...'; nonce unused: default-src * (script-src removed, scripts fall back to *).
  • {"script-src": [CSP.NONCE]} — nonce unused: an empty Content-Security-Policy header (no policy at all).
  • {"script-src": [CSP.SELF, CSP.NONCE]} (recommended) — nonce unused: script-src 'self' (fails closed, unaffected).

So a nonce-only directive silently degrades to its default-src fallback (possibly permissive) or to no policy, on exactly the responses most likely to carry injected markup (error pages, views with no inline nonce'd element). The recommended form — pairing CSP.NONCE with an explicit fallback — already fails closed.

Proposed: a new system check, security.W028, that warns when any SECURE_CSP or SECURE_CSP_REPORT_ONLY directive's only source is CSP.NONCE, hinting to add CSP.SELF, CSP.STRICT_DYNAMIC, or CSP.NONE. It mirrors the existing security.W027 and makes no runtime behavior change. A patch with tests and docs is ready.

An alternative would be to make build_policy() fail closed (keep the directive present as block-all when the nonce is unused), but that changes documented output and would need a release note; a check seems the lower-risk fix.

Change History (0)

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