Content Security Policy
Content Security Policy (CSP) : header HTTP qui permet au serveur d'indiquer au navigateur quelles sources sont autorisées pour charger du contenu (scripts, styles, images, iframes) — rempart principal contre les attaques XSS et l'injection de contenu.
La Content Security Policy (CSP) est un en-tête HTTP qui permet à un serveur d'indiquer au navigateur quelles sources sont autorisées à fournir du contenu exécutable ou affichable dans une page : scripts JavaScript, feuilles de style, images, iframes, polices de caractères, connexions réseau. C'est l'un des mécanismes de défense les plus puissants contre les attaques XSS, à condition d'être configuré avec rigueur — et c'est aussi l'un des plus difficiles à déployer sans rien casser, parce qu'il impose une discipline stricte sur tout ce qui est chargé par le navigateur.
Définition technique
Structure d'une politique CSP
Une CSP est une liste de directives séparées par des points-virgules. Chaque directive contrôle une catégorie de ressources. Par exemple :
Content-Security-Policy:
default-src 'self';
script-src 'self' 'nonce-abc123';
style-src 'self' 'unsafe-inline';
img-src 'self' data: https:;
connect-src 'self' https://api.example.com;
frame-ancestors 'none';
Cette politique autorise par défaut uniquement les ressources provenant du même domaine, avec des exceptions explicites : les scripts doivent venir du même domaine ou porter un nonce valide, les styles inline sont tolérés (concession à WordPress), les images peuvent venir en data: ou en HTTPS, les connexions AJAX sont limitées à un domaine précis, et la page ne peut être affichée dans aucune iframe.
Les directives les plus importantes
default-src: valeur par défaut pour toutes les directives non spécifiées. Commencer par'self'est une bonne base.script-src: contrôle les scripts JavaScript — la directive la plus critique en termes de sécurité.style-src: contrôle les feuilles de style.img-src: contrôle les images.frame-ancestors: remplace l'ancienX-Frame-Options, contrôle qui peut embarquer la page dans une iframe.form-action: limite les destinations des formulaires (protection contre le formjacking).upgrade-insecure-requests: force le navigateur à charger en HTTPS toutes les ressources déclarées en HTTP.report-uri/report-to: indique où envoyer les rapports de violation.
Enjeux actuels
La difficulté du déploiement en production
Appliquer une CSP stricte à une application existante, c'est un exercice délicat. WordPress, par exemple, injecte massivement du JavaScript inline via ses plugins et son éditeur Gutenberg — ce qui rend incompatible une CSP qui interdirait 'unsafe-inline'. La stratégie recommandée consiste à démarrer en mode Content-Security-Policy-Report-Only, analyser les violations remontées par les navigateurs, identifier les sources légitimes et les ajouter à la politique, puis passer en mode bloquant quand on a la preuve que rien ne casse.
Nonces et hashes pour autoriser du code inline
Quand on ne peut pas éliminer complètement le JavaScript inline, la CSP offre deux mécanismes d'exception précis :
- Nonce — une chaîne aléatoire générée par le serveur à chaque requête, incluse à la fois dans l'en-tête CSP et dans chaque balise
<script>autorisée. Le navigateur n'exécute que les scripts portant le bon nonce. Un attaquant qui injecte un script ne connaît pas le nonce courant, son script est donc bloqué. - Hash — un hash SHA-256 du contenu exact du script inline. Cette méthode est plus adaptée aux sites statiques où le contenu inline est connu à l'avance et ne change pas.
CSP et supply chain
Au-delà de la protection XSS, la CSP est un rempart contre les attaques de supply chain front-end. Si un attaquant compromet un CDN tiers ou un outil d'analytics, une CSP stricte empêche l'injection de scripts malveillants parce que le nouveau script viole la politique. Des incidents récents (British Airways, Ticketmaster) ont montré que la supply chain front-end est un vecteur d'attaque significatif — une CSP bien configurée aurait limité l'exposition.
Applications pratiques
Sur WordPress, la CSP est typiquement gérée par un plugin de sécurité, ce qui pose les problèmes classiques des plugins (surface d'attaque, configuration non versionnée, performance). Une approche alternative consiste à gérer la CSP via un fichier de configuration infrastructure, avec plusieurs modes pilotés par une variable d'environnement — off, permissive, report-only, strict — pour permettre un déploiement progressif. Je détaille cette approche dans mon article sur la sécurisation de WordPress sans plugins.
Questions fréquentes
Contre quoi la CSP protège-t-elle concrètement ?
La CSP est conçue principalement pour neutraliser les attaques XSS (Cross-Site Scripting) : même si un attaquant parvient à injecter du JavaScript dans une page, la CSP empêche le navigateur d'exécuter ce script s'il ne provient pas d'une source autorisée. Elle protège aussi contre le clickjacking (via la directive frame-ancestors), l'injection de ressources tierces non autorisées (typosquatting de CDN, supply chain attacks) et le formjacking (redirection de formulaires vers des serveurs malveillants via form-action).
Quelle est la différence entre Content-Security-Policy et Content-Security-Policy-Report-Only ?
Le header standard Content-Security-Policy bloque tout ce qui viole la politique. Le header Content-Security-Policy-Report-Only signale les violations (via un endpoint de reporting) mais ne bloque rien. C'est la méthode recommandée pour déployer progressivement une CSP : on commence en mode observation sur un environnement de staging, on analyse les violations remontées, on corrige les faux positifs, puis on passe en mode bloquant en production une fois qu'on est sûr de ne plus casser l'expérience utilisateur.
Qu'est-ce qu'un nonce CSP et à quoi sert-il ?
Un nonce (number used once) est une chaîne aléatoire générée par le serveur à chaque requête. Le serveur l'inclut à la fois dans l'en-tête CSP (script-src 'nonce-abc123') et dans chaque balise <script> qu'il souhaite autoriser (<script nonce="abc123">). Le navigateur n'exécute que les scripts portant le bon nonce. Cette technique permet d'autoriser précisément le code inline légitime tout en bloquant tout script injecté par un attaquant, qui ne connaîtra pas le nonce de la requête en cours.