Skip to content

Commit 6d5cc6c

Browse files
committed
Prep for 4.0 release
1 parent 9d06e25 commit 6d5cc6c

File tree

2 files changed

+167
-1
lines changed

2 files changed

+167
-1
lines changed

CHANGES.md

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,172 @@
11
CHANGES
22
=======
33

4+
4.0
5+
===
6+
7+
This release contains several breaking changes. For a complete migration guide, see:
8+
https://django-csp.readthedocs.io/en/latest/migration-guide.html
9+
10+
## Breaking Changes
11+
12+
- **Configuration Format**: Moved to dict-based configuration which allows for setting policies for
13+
both enforced and report-only. Instead of using individual settings with `CSP_` prefixes, you now
14+
use dictionaries called `CONTENT_SECURITY_POLICY` and/or `CONTENT_SECURITY_POLICY_REPORT_ONLY`.
15+
([#219](https://github.com/mozilla/django-csp/pull/219))
16+
17+
You can use Django's check command to automatically identify existing CSP settings and generate a
18+
template for the new configuration format:
19+
20+
```
21+
python manage.py check
22+
```
23+
24+
This will detect your old `CSP_` prefixed settings and output a draft of the new dict-based
25+
configuration, giving you a starting point for migration.
26+
27+
**Example:**
28+
29+
Change from:
30+
```python
31+
CSP_DEFAULT_SRC = ["'self'", "*.example.com"]
32+
CSP_SCRIPT_SRC = ["'self'", "js.cdn.com/example/"]
33+
CSP_IMG_SRC = ["'self'", "data:", "example.com"]
34+
CSP_EXCLUDE_URL_PREFIXES = ["/admin"]
35+
```
36+
37+
to:
38+
```python
39+
from csp.constants import SELF
40+
41+
CONTENT_SECURITY_POLICY = {
42+
"DIRECTIVES": {
43+
"default-src": [SELF, "*.example.com"],
44+
"script-src": [SELF, "js.cdn.com/example/"],
45+
"img-src": [SELF, "data:", "example.com"],
46+
},
47+
"EXCLUDE_URL_PREFIXES": ["/admin"],
48+
}
49+
```
50+
51+
- **Nonce Configuration**: Switched from specifying directives that should contain nonces as a
52+
separate list to using a sentinel `NONCE` value in the directive itself.
53+
([#223](https://github.com/mozilla/django-csp/pull/223))
54+
55+
**Example:**
56+
57+
Change from:
58+
```python
59+
CSP_INCLUDE_NONCE_IN = ['script-src', 'style-src']
60+
```
61+
62+
to:
63+
```python
64+
from csp.constants import NONCE, SELF
65+
66+
CONTENT_SECURITY_POLICY = {
67+
"DIRECTIVES": {
68+
"script-src": [SELF, NONCE],
69+
"style-src": [SELF, NONCE],
70+
}
71+
}
72+
```
73+
74+
- **Nonce Behavior**: Changed how `request.csp_nonce` works - it is now Falsy
75+
(`bool(request.csp_nonce)`) until it is read as a string (e.g., used in a template or with
76+
`str(request.csp_nonce)`). Previously, it always tested as `True`, and testing generated the nonce.
77+
([#270](https://github.com/mozilla/django-csp/pull/270))
78+
79+
**Before:**
80+
```python
81+
# The nonce was generated when this was evaluated
82+
if request.csp_nonce:
83+
# Do something with nonce
84+
```
85+
86+
**After:**
87+
```python
88+
# This won't generate the nonce, and will evaluate to False until nonce is read as a string
89+
if request.csp_nonce:
90+
# This code won't run until nonce is used as a string
91+
92+
# To generate and use the nonce
93+
nonce_value = str(request.csp_nonce)
94+
```
95+
96+
- Dropped support for Django ≤3.2.
97+
- Dropped support for Python 3.8.
98+
99+
## New Features and Improvements
100+
101+
- **Dual Policy Support**: Added support for enforced and report-only policies simultaneously using
102+
the separate `CONTENT_SECURITY_POLICY` and `CONTENT_SECURITY_POLICY_REPORT_ONLY` settings.
103+
104+
**Example:**
105+
```python
106+
from csp.constants import NONE, SELF
107+
108+
# Enforced policy
109+
CONTENT_SECURITY_POLICY = {
110+
"DIRECTIVES": {
111+
"default-src": [SELF, "cdn.example.net"],
112+
"frame-ancestors": [SELF],
113+
},
114+
}
115+
116+
# Report-only policy (stricter for testing)
117+
CONTENT_SECURITY_POLICY_REPORT_ONLY = {
118+
"DIRECTIVES": {
119+
"default-src": [NONE],
120+
"script-src": [SELF],
121+
"style-src": [SELF],
122+
"report-uri": "https://example.com/csp-report/",
123+
},
124+
}
125+
```
126+
127+
- **CSP Constants**: Added CSP keyword constants in `csp.constants` (e.g., `SELF` instead of
128+
`"'self'"`) to minimize quoting mistakes and typos.
129+
([#222](https://github.com/mozilla/django-csp/pull/222))
130+
131+
**Example:**
132+
133+
Change from:
134+
```python
135+
CSP_DEFAULT_SRC = ["'self'", "'none'"]
136+
```
137+
138+
to:
139+
```python
140+
from csp.constants import SELF, NONE
141+
142+
CONTENT_SECURITY_POLICY = {
143+
"DIRECTIVES": {
144+
"default-src": [SELF, NONE], # No need to worry about quoting
145+
}
146+
}
147+
```
148+
149+
- Added comprehensive type hints. ([#228](https://github.com/mozilla/django-csp/pull/228))
150+
- Added `EXCLUDE_URL_PREFIXES` check not a string. ([#252](https://github.com/mozilla/django-csp/pull/252))
151+
- Added support for CSP configuration as sets. ([#251](https://github.com/mozilla/django-csp/pull/251))
152+
- Changed `REPORT_PERCENTAGE` to be a float between `0.0` and `100.0` and improved behavior for 100%
153+
report percentage to always send CSP reports.
154+
- Added ability to read the nonce after response if it was included in the header. This will raise
155+
an error when nonce is accessed after response if not already generated.
156+
([#269](https://github.com/mozilla/django-csp/pull/269))
157+
- Made changes to simplify middleware logic and make `CSPMiddleware` easier to subclass. The updated
158+
middleware returns a PolicyParts dataclass that can be modified before the policy is built.
159+
([#237](https://github.com/mozilla/django-csp/pull/237))
160+
161+
## Other Changes
162+
163+
- Added Python 3.13 support.
164+
- Added support for Django 5.1 and 5.2.
165+
- Documentation improvements including fixed trusted_types links and clarification on NONE vs Python's None.
166+
- Documentation note that reporting percentage needs rate limiting middleware.
167+
- Expanded ruff configuration and moved into pyproject.toml.
168+
169+
4170
4.0b7
5171
=====
6172
- Removed ``CSPMiddlewareAlwaysGenerateNonce`` middleware that forced nonce headers when not used in

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ requires = [ "setuptools>=61.2" ]
44

55
[project]
66
name = "django-csp"
7-
version = "4.0b7"
7+
version = "4.0"
88
description = "Django Content Security Policy support."
99
readme = "README.rst"
1010
license = { text = "BSD" }

0 commit comments

Comments
 (0)