Opened 8 hours ago
Last modified 61 minutes ago
#36825 assigned New feature
CSP nonces are not applied in the Django admin
| Reported by: | Carsten Fuchs | Owned by: | Kundan Yadav |
|---|---|---|---|
| Component: | contrib.admin | Version: | 6.0 |
| Severity: | Normal | Keywords: | CSP, nonce, admin |
| Cc: | Rob Hudson, Antoliny | Triage Stage: | Accepted |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description (last modified by )
When a Content Security Policy is configured in settings.py with directives that require script nonces, for example:
SECURE_CSP = { "object-src": [CSP.NONE], "base-uri": [CSP.NONE], "script-src": [CSP.NONCE, CSP.STRICT_DYNAMIC], }
the Django admin interface stops working because the linked scripts used by the admin do not receive a nonce, resulting in CSP violations.
Expected behavior:
When CSP nonces are enabled, the Django admin should either automatically apply nonces to its scripts, or there should be a documented and supported way to make the admin compatible with nonce-based CSP configurations.
Change History (6)
comment:1 by , 8 hours ago
| Description: | modified (diff) |
|---|
comment:2 by , 8 hours ago
| Cc: | added |
|---|---|
| Triage Stage: | Unreviewed → Accepted |
| Type: | Uncategorized → New feature |
comment:3 by , 7 hours ago
Hello Natalia,
thanks for accepting the ticket. I’d love to help and I can try, but realistically this might land closer to Django 61.0 than 6.1 — I don’t know the admin codebase well enough to move that quickly. 🙂 So, no promises.
comment:4 by , 6 hours ago
| Owner: | set to |
|---|---|
| Status: | new → assigned |
comment:5 by , 3 hours ago
This is a subtle issue with regards to the nature of strict-dynamic.
The admin templates would need to add conditional nonce attributes to all script tags (both external and inline). For example:
Current (admin/base.html:9)
<script src="{% static "admin/js/theme.js" %}"></script>
Should be:
<script src="{% static "admin/js/theme.js" %}"{% if csp_nonce %} nonce="{{ csp_nonce }}"{% endif %}></script>
This would allow things to work in the following 4 scenarios. (Currently it seems Django 6.0 supports the first 3):
- when CSP middleware is not enabled (nonce is falsy, not added to header or script tags)
- when CSP is enabled without nonces (nonce not accessed, not added to header or script tags)
- when CSP uses nonces (nonce added to both tag and header)
- when CSP uses nonces with
CSP.STRICT_DYNAMIC(nonce added to both tag and header)
The difference between 3 and 4 is that 3 would allow host-based allowlists and keyword allowlists to work. When CSP.STRICT_DYNAMIC, host-based allowlists and keyword (e.g. CSP.SELF) allowlists are ignored, so admin scripts would then require nonces.
comment:6 by , 61 minutes ago
| Cc: | added |
|---|
Hello Carsten!
Thank you for taking the time to create this report. I have confirmed your findings:
I am accepting this ticket as a new feature for 6.1, subject to volunteer contributions, to add nonce-based CSP support in the admin. Would you like to work on a branch?