CSP (Content Security Policy) : le header qui bloque les injections
La CSP est probablement le header de sécurité le plus puissant et le plus difficile à déployer correctement. Une CSP bien calibrée coupe net les attaques XSS et les injections de ressources tierces non autorisées. Une CSP mal configurée casse le site en production sous les yeux des visiteurs. Voici ce qu'on regarde en audit, comment on l'active sans catastrophe, et les erreurs qu'on corrige chez nos clients WordPress et PrestaShop.
Définition en une phrase
La Content Security Policy (CSP) est un en-tête HTTP qui indique au navigateur la liste exacte des sources autorisées pour charger des scripts, styles, images et frames sur votre page.
En clair, pour les non-initiés. Sans CSP, un attaquant qui trouve une faille dans votre site peut injecter un script depuis n'importe quel serveur tiers, et le navigateur l'exécutera sans broncher. Avec une CSP stricte, le navigateur refuse toute ressource qui ne figure pas sur votre liste blanche, même si le code est déjà dans votre page.
Pourquoi c'est important pour votre site
Les attaques XSS (Cross-Site Scripting) représentent l'une des catégories de vulnérabilités web les plus exploitées. Une CSP correctement configurée ajoute une couche de défense en profondeur : même si un attaquant parvient à injecter du code dans votre HTML (via un commentaire, un champ de formulaire mal protégé ou un plugin tiers compromis), la politique bloquera l'exécution du script tiers.
Concrètement, sur les sites e-commerce, une CSP bien posée coupe aussi le vecteur des skimmers : un script malveillant cherchant à exfiltrer des données de carte bancaire vers un domaine extérieur sera bloqué au niveau du navigateur.
Dans nos audits P.01, CSP est absente sur plus de 80 % des WordPress et 90 % des PrestaShop qu'on inspecte. Quand elle est présente, elle est souvent en mode report-only avec unsafe-inline partout, ce qui revient à ne rien protéger.
Comment ça fonctionne, concrètement
La CSP s'envoie via un en-tête HTTP Content-Security-Policy ou via une balise <meta> dans le <head> (mais la balise <meta> ne couvre pas toutes les directives, on préfère l'en-tête serveur).
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-XYZ123'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https://cdn.exemple.fr; frame-ancestors 'none';
Les directives principales :
default-src 'self': par défaut, toutes les ressources doivent venir du même domaine.script-src: contrôle les scripts JavaScript. C'est la directive critique.'unsafe-inline'et'unsafe-eval'la rendent inefficace contre le XSS.style-src: contrôle les feuilles de style CSS.img-src: sources autorisées pour les images.connect-src: contrôle les requêtes AJAX/fetch/WebSocket.frame-ancestors: remplaceX-Frame-Options, contrôle qui peut intégrer votre page dans un<iframe>.report-uri/report-to: envoie les violations à un endpoint pour audit, sans bloquer.
La directive 'nonce-XYZ123' permet d'autoriser un script inline spécifique sans ouvrir 'unsafe-inline'. Le nonce est un jeton unique généré côté serveur à chaque requête.
Phase de déploiement recommandée
- Commencer en
Content-Security-Policy-Report-Onlypour observer les violations sans rien casser. - Analyser les violations remontées pendant 1 à 2 semaines.
- Affiner les directives pour couvrir les ressources légitimes (analytics, fonts, CDN de build).
- Basculer en
Content-Security-Policybloquant.
Comment Secushot configure la CSP en intervention
Dans notre protocole P.03 Durcissement et le pack PK.CFE Sérénité Cloudflare, la CSP suit systématiquement cette séquence :
Sur WordPress :
WordPress est particulièrement complexe à couvrir avec une CSP stricte parce que de nombreux plugins injectent des scripts inline et des ressources tierces sans déclarer leurs dépendances. Notre approche :
- On déploie
Content-Security-Policy-Report-Onlysur le site en production. - On navigue manuellement sur les pages critiques (accueil, panier, checkout, admin) pour générer des violations représentatives.
- On consolide la liste des sources légitimes à autoriser.
- On pose la CSP bloquante avec les sources identifiées.
'unsafe-inline'est évité si possible, remplacé par des nonces côté PHP/WordPress.
Content-Security-Policy:
default-src 'self';
script-src 'self' https://www.google-analytics.com https://www.googletagmanager.com;
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
font-src 'self' https://fonts.gstatic.com;
img-src 'self' data: https:;
connect-src 'self' https://www.google-analytics.com;
frame-ancestors 'none';
upgrade-insecure-requests;
Sur PrestaShop :
PrestaShop charge de nombreuses ressources depuis des CDN et des modules tiers. Le travail d'inventaire est plus long, surtout sur les versions 1.6/1.7 avec beaucoup de modules marchands. On adapte systématiquement connect-src pour couvrir les appels API de paiement (Stripe, PayPal, Mollie).
Via Cloudflare Transform Rules :
Quand on ne peut pas modifier les headers serveur directement (hébergement partagé sans accès .htaccess complet), on pose la CSP via une règle Cloudflare Transform Rule / HTTP Response Header Modification. C'est la solution qu'on applique sur la majorité des clients PK.CFE.
Les erreurs qu'on rencontre le plus souvent
1. 'unsafe-inline' dans script-src
C'est la principale. Ajouter 'unsafe-inline' dans script-src annule quasi-totalement la protection contre le XSS. On la voit partout parce que WordPress et ses plugins en dépendent massivement. La correction propre passe par les nonces PHP ou le passage aux modules ES avec type="module". C'est un chantier, c'est pourquoi on ne met pas 'unsafe-inline' dans script-src dans notre configuration de base : on préfère lister explicitement chaque domaine source.
2. CSP posée via balise <meta> uniquement
La directive frame-ancestors ne fonctionne pas dans une balise <meta>. Pour le clickjacking, seul l'en-tête HTTP Content-Security-Policy (ou X-Frame-Options) est pris en compte. On voit des sites qui croient être protégés contre le framing alors qu'ils ne le sont pas.
3. Mode report-only oublié en production
On audite régulièrement des sites qui ont une CSP en mode Content-Security-Policy-Report-Only depuis plusieurs mois. La politique observe mais ne bloque rien. C'est une étape de test, pas un état final. La confusion vient souvent d'une agence qui a posé le header lors d'un audit sans finaliser le déploiement.
4. Aucune directive upgrade-insecure-requests
Sur les sites qui ont du contenu mixte (images ou scripts servis en HTTP sur un site HTTPS), upgrade-insecure-requests force le navigateur à convertir toutes les URLs HTTP en HTTPS avant la requête. Cette directive est complémentaire de HSTS (voir HSTS) et souvent oubliée dans les CSP déployées à la main.
5. connect-src trop restrictif bloquant les API tierces
Une CSP stricte sans connect-src élargi aux domaines de paiement casse silencieusement Stripe.js ou PayPal. Le navigateur bloque l'appel XHR vers l'API de paiement, le client voit une erreur opaque, et la vente est perdue. On vérifie systématiquement connect-src sur les sites e-commerce avant livraison.
Questions fréquentes
Est-ce que la CSP remplace un WAF ? Non. La CSP protège le navigateur du visiteur contre l'exécution de code non autorisé. Un WAF comme le Cloudflare WAF protège votre serveur contre les requêtes malveillantes entrantes. Les deux opèrent à des niveaux différents. Sur les sites sensibles, on pose les deux.
WordPress est-il compatible avec une CSP stricte ? Partiellement. Le noyau WordPress peut être rendu compatible, mais la majorité des plugins tiers injectent des scripts inline ou chargent des ressources depuis leurs propres CDN. Une CSP stricte sur un WordPress avec 15 plugins actifs demande un inventaire sérieux. On y passe en moyenne 4 à 6 heures lors d'un P.03.
Faut-il une CSP si on utilise Cloudflare ? Oui, pour une raison précise : le WAF Cloudflare filtre les requêtes malveillantes entrantes, mais ne peut pas bloquer un script malveillant qui s'exécute dans le navigateur du visiteur après avoir été injecté dans votre HTML. La CSP couvre ce second vecteur.
Peut-on déployer une CSP sans toucher au serveur ? Via Cloudflare Transform Rules, oui. C'est ce qu'on fait pour les clients sur hébergement partagé ou avec une stack dont on ne maîtrise pas l'accès serveur direct. La protection est identique, le déploiement est plus rapide.
Comment savoir si ma CSP actuelle est correcte ?
Deux pistes : activer report-uri et surveiller les violations pendant une semaine, ou utiliser l'outil securityheaders.com pour un score rapide. Nos audits P.01 incluent une vérification de la CSP avec signalement de sévérité haute en cas d'absence ou de configuration permissive.
La CSP ralentit-elle mon site ? Non. C'est un en-tête HTTP de quelques octets, sans impact mesurable sur les performances. L'impact, si on en voit un, vient d'une mauvaise configuration qui bloque des ressources légitimes et force des chargements en erreur.
Pour aller plus loin
- Connexe : HSTS, Cloudflare WAF, SPF / DKIM / DMARC.
- Protocoles concernés : la CSP est configurée dans le durcissement sécurité P.03 et auditée (sans activation) dans l'audit préventif P.01. Elle fait partie du scope du pack Sérénité Cloudflare PK.CFE quand les headers sont déployés via Cloudflare.
CSP absente ou mal configurée sur votre site ? Notre durcissement sécurité (P.03, 790 € TTC, livré en 72 h) inclut l'audit et le déploiement de la CSP, des headers HTTP, du WAF et du rate limiting. Rapport PDF avant/après. Briefer un durcissement P.03