Modifying the Policy with Decorators
Content Security Policies should be restricted and paranoid by default. You may, on some views, need to expand or change the policy. django-csp includes four decorators to help.
All decorators take an optional keyword argument, REPORT_ONLY
, which defaults to False
. If
set to True
, the decorator will update the report-only policy instead of the enforced policy.
@csp_exempt
Using the @csp_exempt
decorator disables the CSP header on a given
view.
from csp.decorators import csp_exempt
# Will not have a CSP header.
@csp_exempt()
def myview(request):
return render(...)
# Will not have a CSP report-only header.
@csp_exempt(REPORT_ONLY=True)
def myview(request):
return render(...)
You can manually set this on a per-response basis by setting the _csp_exempt
or _csp_exempt_ro
attribute on the response to True
:
# Also will not have a CSP header.
def myview(request):
response = render(...)
response._csp_exempt = True
return response
@csp_update
The @csp_update
header allows you to append values to the source lists specified in the
settings. If there is no setting, the value passed to the decorator will be used verbatim.
Note
To quote the CSP spec: “There’s no inheritance; … the default list is not used for that resource type” if it is set. E.g., the following will not allow images from ‘self’:
default-src ‘self’; img-src imgsrv.com
The arguments to the decorator are the same as the settings. The
decorator expects a single dictionary argument, where the keys are the directives and the values
are either strings, lists or tuples. An optional argument, REPORT_ONLY
, can be set to True
to update the report-only policy instead of the enforced policy.
from csp.decorators import csp_update
# Will append imgsrv.com to the list of values for `img-src` in the enforced policy.
@csp_update({"img-src": "imgsrv.com"})
def myview(request):
return render(...)
# Will append cdn-img.com to the list of values for `img-src` in the report-only policy.
@csp_update({"img-src": "cdn-img.com"}, REPORT_ONLY=True)
def myview(request):
return render(...)
@csp_replace
The @csp_replace
decorator allows you to replace a source list specified in settings. If
there is no setting, the value passed to the decorator will be used verbatim. (See the note under
@csp_update
.) If the specified value is None, the corresponding key will not be included.
The arguments and values are the same as @csp_update
:
from csp.decorators import csp_replace
# Will allow images only from imgsrv2.com in the enforced policy.
@csp_replace({"img-src": "imgsrv2.com"})
def myview(request):
return render(...)
# Will allow images only from cdn-img2.com in the report-only policy.
@csp_replace({"img-src": "cdn-img2.com"}, REPORT_ONLY=True)
def myview(request):
return render(...)
The csp_replace
decorator can also be used to remove a directive from the policy by setting the
value to None
. For example, if the frame-ancestors
directive is set in the Django settings
and you want to remove the frame-ancestors
directive from the policy for this view:
from csp.decorators import csp_replace
@csp_replace({"frame-ancestors": None})
def myview(request):
return render(...)
@csp
If you need to set the entire policy on a view, ignoring all the settings, you can use the @csp
decorator. This can be stacked to update both the enforced policy and the report-only policy if both
are in use, as shown below.
from csp.constants import SELF, UNSAFE_INLINE
from csp.decorators import csp
@csp(
{
"default-src": [SELF],
"img-src": ["imgsrv.com"],
"script-src": ["scriptsrv.com", "googleanalytics.com", UNSAFE_INLINE],
}
)
@csp(
{
"default-src": [SELF],
"img-src": ["imgsrv.com"],
"script-src": ["scriptsrv.com", "googleanalytics.com"],
"frame-src": [SELF],
},
REPORT_ONLY=True,
)
def myview(request):
return render(...)