Django CSP
django-csp provides robust Content Security Policy (CSP) support for Django applications. It helps mitigate cross-site scripting (XSS) and other code injection attacks by adding CSP headers to HTTP responses. The latest major version is 4.0, which introduced significant breaking changes to its configuration format. The project is actively maintained, typically releasing updates to support new Django and Python versions.
Warnings
- breaking The configuration format changed significantly in v4.0. Old `CSP_` prefixed settings (e.g., `CSP_DEFAULT_SRC`, `CSP_REPORT_ONLY`) are removed. Policies must now be defined using dictionaries `CONTENT_SECURITY_POLICY` and `CONTENT_SECURITY_POLICY_REPORT_ONLY`.
- breaking The `CSPMiddlewareAlwaysGenerateNonce` middleware and the `CSP_ALWAYS_GENERATE_NONCE` setting were removed in v4.0. Nonce generation is now controlled by `CSP_AUTO_NONCE` or `CSP_NONCE_URL_PREFIXES`.
- gotcha For nonce-based CSP, inline scripts and styles require the `nonce` attribute. While `CSP_AUTO_NONCE = True` generates a nonce, you *must* use the `{% csp_nonce %}` template tag to apply it to your inline elements.
- gotcha If you use the `report-uri` directive with `CSP_REPORT_PERCENTAGE`, you should implement rate limiting on the `/csp-report/` endpoint to prevent abuse and denial-of-service attacks, as browsers may send many reports.
Install
-
pip install django-csp
Imports
- CSPMiddleware
from csp.middleware import CSPMiddleware
- CSPReportMiddleware
from csp.middleware import CSPReportMiddleware
- nonce
from csp.utils import nonce
- CSPMiddlewareAlwaysGenerateNonce
N/A
Quickstart
# settings.py
INSTALLED_APPS = [
# ...
"csp",
]
MIDDLEWARE = [
# ...
"csp.middleware.CSPMiddleware",
# Optionally, for reporting only:
# "csp.middleware.CSPReportMiddleware",
# ...
]
# Basic CSP policy, enforce for all pages by default
CONTENT_SECURITY_POLICY = {
"default-src": ["'self'"],
"script-src": ["'self'", "'unsafe-inline'", "'unsafe-eval'", "'nonce-{{ nonce }}'"],
"style-src": ["'self'", "'unsafe-inline'", "'nonce-{{ nonce }}'"],
"img-src": ["'self'", "data:", "https://example.com"],
"report-uri": ["/csp-report/"],
}
# To enable automatic nonce generation (recommended for inline scripts/styles)
CSP_AUTO_NONCE = True
# urls.py
from django.urls import path
from django.views.decorators.csrf import csrf_exempt
from csp.views import report
urlpatterns = [
# Your other URLs...
path("csp-report/", csrf_exempt(report), name="csp-report"),
]
# In your templates (e.g., base.html) to apply nonce to inline elements:
# {% load csp %}
# <script nonce="{% csp_nonce %}">...</script>
# <style nonce="{% csp_nonce %}">...</style>