Politique de sécurité de contenu (CSP)¶
La politique de sécurité de contenu (CSP) est un standard de sécurité web aidant à prévenir les attaques par injection de contenu en limitant les sources à partir desquelles le contenu peut être chargé. Elle joue un rôle important dans le cadre d’une stratégie de sécurité complète.
Pour des instructions de configuration dans un projet Django, consultez la documentation Utilisation de CSP. Pour un guide HTTP au sujet de CSP, consultez le guide MDN sur CSP.
Aperçu¶
La spécification Content-Security-Policy définit deux en-têtes complémentaires :
Content-Security-Policy: applique la politique CSP, en bloquant le contenu qui viole les directives définies.Content-Security-Policy-Report-Only: signale les violations CSP sans bloquer le contenu, permettant de tester sans dommage.
Chaque politique est composée d’une ou de plusieurs directives avec leurs valeurs, qui indiquent ensemble au navigateur la façon de gérer des types spécifiques de contenus.
Lorsque ContentSecurityPolicyMiddleware est activé, Django construit et lie automatiquement les en-têtes appropriés à chaque réponse en fonction des réglages configurés, sauf s’ils ont déjà été définis par une autre couche.
Réglages¶
ContentSecurityPolicyMiddleware est configuré en utilisant les réglages suivants:
SECURE_CSP: définit la politique de sécurité de contenu comme appliquée.SECURE_CSP_REPORT_ONLY: définit la politique de sécurité de contenu en mode signalement uniquement.
Ces réglages peuvent être définis indépendamment ou conjointement.
Utilisez
SECURE_CSPseul pour appliquer une politique qui a déjà été testée et vérifiée.Use
SECURE_CSP_REPORT_ONLYon its own to evaluate a new policy without disrupting site behavior. This mode does not block violations, it only logs them. It’s useful for testing and monitoring, but provides no protection against active threats.Use both to maintain an enforced baseline while experimenting with changes. Even for well-established policies, continuing to collect reports reports can help detect regressions, unexpected changes in behavior, or potential tampering in production environments.
Policy violation reports¶
When a CSP violation occurs, browsers typically log details to the developer
console, providing immediate feedback during development. To also receive these
reports programmatically, the policy must include a reporting directive
such as report-uri that specifies where violation data should be sent.
Django supports configuring these directives via the
SECURE_CSP_REPORT_ONLY settings, but reports will only be issued by
the browser if the policy explicitly includes a valid reporting directive.
Django does not provide built-in functionality to receive, store, or process violation reports. To collect and analyze them, you must implement your own reporting endpoint or integrate with a third-party monitoring service.
CSP constants¶
Django provides predefined constants representing common CSP source expression
keywords such as 'self', 'none', and 'unsafe-inline'. These
constants are intended for use in the directive values defined in the settings.
They are available through the CSP enum, and using
them is recommended over raw strings. This helps avoid common mistakes such as
typos, improper quoting, or inconsistent formatting, and ensures compliance
with the CSP specification.
- class CSP[source]¶
Enum providing standardized constants for common CSP source expressions.
- NONE¶
Represents
'none'. Blocks loading resources for the given directive.
- REPORT_SAMPLE¶
Represents
'report-sample'. Instructs the browser to include a sample of the violating code in reports. Note that this may expose sensitive data.
- SELF¶
Represents
'self'. Allows loading resources from the same origin (same scheme, host, and port).
- STRICT_DYNAMIC¶
Represents
'strict-dynamic'. Allows execution of scripts loaded by a trusted script (e.g., one with a valid nonce or hash), without needing'unsafe-inline'.
- UNSAFE_EVAL¶
Represents
'unsafe-eval'. Allows use ofeval()and similar JavaScript functions. Strongly discouraged.
- UNSAFE_HASHES¶
Represents
'unsafe-hashes'. Allows inline event handlers and somejavascript:URIs when their content hashes match a policy rule. Requires CSP Level 3+.
- UNSAFE_INLINE¶
Represents
'unsafe-inline'. Allows execution of inline scripts, styles, andjavascript:URLs. Generally discouraged, especially for scripts.
- WASM_UNSAFE_EVAL¶
Represents
'wasm-unsafe-eval'. Permits compilation and execution of WebAssembly code without enabling'unsafe-eval'for scripts.
- NONCE¶
Django-specific placeholder value (
"<CSP_NONCE_SENTINEL>") used inscript-srcorstyle-srcdirectives to activate nonce-based CSP. This string is replaced at runtime by theContentSecurityPolicyMiddlewarewith a secure, random nonce that is generated for each request. See detailed explanation in Nonce usage.
Décorateurs¶
Django provides decorators to control the Content Security Policy headers on a
per-view basis. These allow overriding or disabling the enforced or report-only
policy for specific views, providing fine-grained control when the global
settings are not sufficient. Applying these overrides fully replaces the base
CSP: they do not merge with existing rules. They can be used alongside the
constants defined in CSP.
Avertissement
Weakening or disabling a CSP policy on any page can compromise the security of the entire site. Because of the « same origin » policy, an attacker could exploit a vulnerability on one page to access other parts of the site.
- csp_override(config)(view)[source]¶
Overrides the
Content-Security-Policyheader for the decorated view using directives in the same format as theSECURE_CSPsetting.The
configargument must be a mapping with the desired CSP directives. Ifconfigis an empty mapping ({}), no CSP enforcement header will be added to the response returned by that view, effectively disabling CSP for that view.Exemples :
from django.http import HttpResponse from django.utils.csp import CSP from django.views.decorators.csp import csp_override @csp_override( { "default-src": [CSP.SELF], "img-src": [CSP.SELF, "data:"], } ) def my_view(request): return HttpResponse("Custom Content-Security-Policy header applied") @csp_override({}) def my_other_view(request): return HttpResponse("No Content-Security-Policy header added")
- csp_report_only_override(config)(view)[source]¶
Overrides the
Content-Security-Policy-Report-Onlyheader for the decorated view using directives in the same format as theSECURE_CSP_REPORT_ONLYsetting.Like
csp_override(), theconfigargument must be a mapping with the desired CSP directives. Ifconfigis an empty mapping ({}), no CSP report-only header will be added to the response returned by that view, effectively disabling report-only CSP for that view.Exemples :
from django.http import HttpResponse from django.utils.csp import CSP from django.views.decorators.csp import csp_report_only_override @csp_report_only_override( { "default-src": [CSP.SELF], "img-src": [CSP.SELF, "data:"], "report-uri": "https://mysite.com/csp-report/", } ) def my_view(request): return HttpResponse("Custom Content-Security-Policy-Report-Only header applied") @csp_report_only_override({}) def my_other_view(request): return HttpResponse("No Content-Security-Policy-Report-Only header added")
The examples above assume function-based views. For class-based views, see the guide for decorating class-based views.
Nonce usage¶
A CSP nonce (« number used once ») is a unique, random value generated per HTTP
response. Django supports nonces as a secure way to allow specific inline
<script> or <style> elements to execute without relying on
'unsafe-inline'.
Nonces are enabled by including the special placeholder
NONCE in the relevant directive(s) of your
CSP settings, such as script-src or style-src.
When present, the
ContentSecurityPolicyMiddleware
will generate a nonce and insert the corresponding nonce-<value> source
expression into the CSP header.
To use this nonce in templates, the
csp() context processor needs to be
enabled. It adds a csp_nonce variable to the template context, allowing
inline elements to include a matching nonce="{{ csp_nonce }}" attribute in
inline scripts or styles.
The browser will only execute inline elements that include a nonce=<value>
attribute matching the one specified in the Content-Security-Policy (or
Content-Security-Policy-Report-Only) header. This mechanism provides
fine-grained control over which inline code is allowed to run.
If a template includes {{ csp_nonce }} but the policy does not include
NONCE, the HTML will include a nonce attribute,
but the header will lack the required source expression. In this case, the
browser will block the inline script or style (or report it for report-only
configurations).
Nonce generation and caching¶
Django’s nonce generation is lazy: the middleware only generates a nonce if
{{ csp_nonce }} is accessed during template rendering. This avoids
unnecessary work for pages that do not use nonces.
However, because nonces must be unique per request, extra care is needed when using full-page caching (e.g., Django’s cache middleware, CDN caching). Serving cached responses with previously generated nonces may result in reuse across users and requests. Although such responses may still appear to work (since the nonce in the CSP header and HTML content match), reuse defeats the purpose of the nonce and weakens security.
To ensure nonce-based policies remain effective:
Avoid caching full responses that include
{{ csp_nonce }}.If caching is necessary, use a strategy that injects a fresh nonce on each request, or consider refactoring your application to avoid inline scripts and styles altogether.