Temps de lecture estimé : 10 minutes
Points clés à retenir
- Bannir ‘unsafe-inline’ et les sources jokers en script-src
- Toujours tester en report-only avant l’enforcement
- Vérifier la compatibilité nonce/cache CDN avant déploiement
- Utiliser SRI pour sécuriser les ressources tierces
- Mettre en place un monitoring des violations avec SLA de correction
Qu’est-ce que le CSP et pourquoi il compte
La Content Security Policy (CSP) est un en-tête HTTP qui indique au navigateur quelles ressources il a le droit de charger sur une page. Concrètement, ce que ça change c’est la surface d’attaque disponible pour un script malveillant injecté dans votre site. Les pièges du CSP commencent souvent bien avant l’écriture du premier header : ils naissent d’une mauvaise compréhension de ce que la politique protège réellement.
Historique et rôle : prévention des XSS et autres attaques
Le CSP a été conçu à l’origine pour limiter les failles XSS (cross-site scripting), l’une des vulnérabilités web les plus répandues. Selon l’OWASP, une politique CSP bien configurée peut réduire jusqu’à 80 % des vecteurs XSS exploitables côté client. J’ai vu passer ce cas plusieurs fois en mission : des équipes qui pensaient avoir « activé la sécurité » en ajoutant un header, sans jamais vérifier ce qu’il bloquait réellement.
Principaux composants : directives, sources, nonces, hashes
Une politique CSP se construit avec des directives (script-src, style-src, img-src…) associées à des sources autorisées. On peut whitelister un domaine, un nonce unique par requête, ou un hash cryptographique du contenu exact d’un script. Chaque mécanisme a ses forces, mais aussi ses conditions d’usage précises — et c’est souvent là que les erreurs commencent.
Mode rapport-only vs enforcement et quand les utiliser
Le mode Content-Security-Policy-Report-Only journalise les violations sans rien bloquer. C’est la phase de test avant le passage en enforcement (le header CSP classique, qui bloque réellement). Soyons clairs : sauter cette étape, c’est la cause numéro un des incidents de production que je constate chez mes clients.

Les erreurs de base qui annulent le CSP
Certaines erreurs sont si fréquentes qu’elles rendent une politique CSP totalement inefficace, tout en donnant l’illusion d’être protégé. C’est un classique que je retrouve chez mes clients : le header existe, mais il ne sert à rien.
Sources trop larges : ‘unsafe-inline’ et ‘*’
Autoriser ‘unsafe-inline’ dans script-src annule une grande partie de la protection XSS, puisque n’importe quel script injecté dans le HTML pourra s’exécuter. Même chose avec un joker ‘*’ en source : la politique devient décorative. Pour les applications monopages, entre 60 et 75 % des scripts inline peuvent être migrés vers des fichiers externes hachés, ce qui permet de retirer ‘unsafe-inline’ sans tout casser.
Mélange de HTTP/HTTPS et contenus mixtes
Un site en HTTPS qui charge encore une ressource en HTTP déclenche du contenu mixte, souvent bloqué silencieusement par le navigateur. Dans les faits, ce genre de résidu vient presque toujours d’une vieille intégration tierce oubliée lors d’une migration.
Oublier report-uri/report-to en phase de mise au point
Sans point de collecte des violations, vous naviguez à l’aveugle. Les fournisseurs de CDN qui suivent ce type de déploiement rapportent une baisse de 40 à 60 % des faux-positifs en seulement deux semaines de report-only, à condition d’avoir un canal de remontée en place dès le premier jour.
Pièges liés aux nonces et hashes
Les nonces et les hashes sont les outils les plus fins du CSP, mais aussi les plus mal maîtrisés. Autant vous le dire tout de suite : une mauvaise génération de nonce rend toute la politique inutile.
Nonce dynamique mal généré ou réutilisé
Un nonce doit être unique par requête et généré côté serveur avec une source d’aléa cryptographique. Réutiliser le même nonce sur plusieurs pages, ou le générer côté client, annule sa fonction : un attaquant peut alors le deviner ou le réutiliser dans son propre script injecté.
Oublier d’ajouter hash pour scripts inlinés indispensables
Certains scripts inline sont incontournables techniquement (trackers imposés, widgets tiers). Plutôt que d’ouvrir ‘unsafe-inline’ pour eux, on calcule le hash SHA de leur contenu exact et on l’ajoute à la directive. Le hash casse dès que le contenu du script change d’un seul caractère, ce qui oblige à un vrai processus de mise à jour.
Gestion côté serveur lors du caching et CDN
On oublie souvent un détail qui change tout : un nonce généré à chaque requête n’a aucun sens si la page HTML est mise en cache par un CDN. Le nonce figé dans le cache devient prévisible et réutilisable par n’importe quel visiteur, ce qui vide la protection de son sens. La règle est simple : les pages contenant un nonce dynamique ne doivent jamais être servies depuis un cache HTML partagé.
CSP et ressources tierces (CDN, analytics, ads)
Les intégrations tierces sont l’un des points d’entrée les plus fréquents des pièges du CSP, parce qu’elles évoluent hors de votre contrôle direct.
Autorisations excessives pour third-parties
Autoriser un domaine entier de régie publicitaire ou d’analytics dans script-src, c’est faire confiance à tout ce que ce tiers déploiera un jour sur ce domaine. Dans mon expérience, ce type d’autorisation large finit presque toujours par inclure un sous-domaine compromis ou un tag mal audité.
Solutions : sous-domaines dédiés, SRI, règles fines
Le Subresource Integrity (SRI) permet de vérifier qu’un fichier chargé depuis un CDN externe n’a pas été altéré, en comparant son hash au moment du chargement. Cette technique réduit d’environ 90 % le risque lié à un CDN compromis pour les ressources statiques. Combinée à des règles de sources précises plutôt qu’un domaine générique, elle limite fortement l’exposition.
Cas particulier : intégration de widgets et iframes
Les widgets embarqués (chat, avis clients, calendrier de réservation) ajoutent souvent leur propre script ET leur propre iframe. Il faut alors gérer deux directives distinctes, frame-src et script-src, faute de quoi le widget semble « cassé » et l’équipe finit par tout autoriser pour aller plus vite. C’est un classique que je retrouve chez mes clients pressés par un lancement.
Erreurs opérationnelles et mise en production
Une bonne politique CSP peut échouer non pas sur sa conception, mais sur la façon dont elle est déployée.
Passer directement en enforcement sans rapport préalable
Basculer en mode bloquant sans phase de report-only, c’est prendre le risque de casser des fonctionnalités en production sans préavis. Les guides de déploiement recommandent une fenêtre de tuning de 7 à 30 jours en report-only selon le volume de trafic, le temps que les cas rares remontent.
Tests automatisés manquants (CI/CD) et faux-positifs
Sans test automatisé, une politique CSP dérive à chaque déploiement : un nouveau script tiers ajouté par l’équipe marketing, et la page casse en silence. Un pipeline qui simule les rapports de violation en environnement de test évite ce genre de surprise le vendredi soir.
Monitoring des violations et SLA pour corrections
Un CERT ayant étudié des incidents XSS estime le temps moyen de correction d’une violation à 3 à 7 jours une fois détectée. Encore faut-il la détecter : sur le terrain, on compte en moyenne une seule action utile pour dix rapports de violation reçus, d’où l’intérêt d’agréger et de filtrer avant d’alerter une équipe.
Ne traitez jamais le CSP comme une protection unique. Il complète le X-Content-Type-Options, la validation des entrées côté serveur et l’échappement systématique des sorties — pas l’inverse.
Outils, exemples de headers et correctifs prêts à copier
Concrètement, ce que ça change c’est de passer d’une politique théorique à des lignes déployables. Voici trois niveaux, du plus strict au plus permissif, à adapter à votre contexte réel plutôt qu’à copier tel quel.
| Niveau | Exemple de directive | Usage recommandé |
|---|---|---|
| Strict | default-src ‘self’; script-src ‘self’ ‘nonce-xyz’ | Applications neuves, forte exigence sécurité |
| Modéré | default-src ‘self’; script-src ‘self’ https://cdn.exemple.com | Sites avec quelques intégrations tierces stables |
| Report-only | Content-Security-Policy-Report-Only : default-src ‘self’; report-uri /csp-report | Phase de tuning avant enforcement |
Exemples de header CSP strict, modéré, et report-only
Sur Nginx, le header s’ajoute directement au bloc serveur avec add_header Content-Security-Policy suivi de la politique complète sur une seule ligne. Sur Apache, on utilise Header set Content-Security-Policy dans le virtual host ou le .htaccess. Avec Express (Node.js), un middleware dédié comme helmet permet de définir la politique par objet de configuration, ce qui facilite la maintenance dans le temps.
Snippets pour Nginx, Apache et entêtes via framework (Express)
Le point commun aux trois environnements : le header doit être généré dynamiquement si vous utilisez des nonces, jamais codé en dur dans un fichier de configuration statique. Sur Express, cela signifie régénérer le nonce à chaque requête dans le middleware, puis l’injecter à la fois dans le header et dans les balises script du template.
Checklist rapide de débogage (console, network, rapports)
La console développeur du navigateur affiche directement les violations CSP avec la directive concernée. L’onglet réseau permet de vérifier que le header part bien avec la bonne valeur, sans faute de frappe sur une directive. Et les rapports collectés côté serveur restent la seule vue fiable de ce qui se passe chez vos visiteurs, au-delà de vos propres tests.
Mesures chiffrées et ROI sécurité
Face à un dirigeant qui demande pourquoi investir du temps dans les pièges du CSP plutôt qu’ailleurs, les chiffres aident à trancher.
Réduction attendue des XSS exploitables par une CSP correcte
Une politique CSP bien construite, sans ‘unsafe-inline’ ni source générique, réduit fortement la surface d’attaque XSS, avec un effet mesuré jusqu’à 80 % selon l’OWASP sur les vecteurs les plus courants. C’est un argument concret face à des équipes techniques qui doutent encore de la priorité à donner au sujet.
Coût moyen d’une faille XSS vs effort d’implémentation CSP
L’ajout d’un header CSP typique pèse entre 150 et 600 octets par réponse, un coût de performance négligeable comparé au temps de correction d’un incident déjà exploité en production. Le calcul est vite fait : quelques heures de configuration et de tests contre plusieurs jours de gestion de crise.
Indicateurs à suivre (violations/jour, temps de patch)
Deux indicateurs suffisent pour piloter le sujet dans la durée : le nombre de violations par jour (tendance, pas valeur absolue) et le délai moyen entre détection et correction. Dans mes ateliers en entreprise, c’est souvent le seul tableau de bord sécurité que les équipes non techniques arrivent à suivre sans se perdre.
Ressources et bonnes pratiques continues
Une politique CSP n’est jamais figée : elle suit les évolutions du site, des outils tiers et des frameworks utilisés.
Liens vers spécifications et guides officiels (OWASP)
L’OWASP publie un guide de référence sur le CSP, régulièrement mis à jour avec les nouvelles directives du standard. C’est la source à consulter avant d’adopter une directive expérimentale encore peu supportée par les navigateurs.
Processus recommandé : audit, déploiement progressif, revue annuelle
Le processus qui fonctionne le mieux chez mes clients tient en trois temps : un audit initial des sources utilisées, un déploiement progressif en report-only puis en enforcement, et une revue annuelle systématique. Sans cette dernière étape, une politique CSP se dégrade au rythme des nouveaux outils ajoutés par les équipes marketing ou produit.
Templates de politiques pour cas d’usage courants (SPA, CMS, intranet)
Une application monopage, un CMS grand public et un intranet d’entreprise n’ont pas les mêmes contraintes de sources tierces ni le même niveau de risque. Dans les faits, mieux vaut partir d’un gabarit adapté à chaque contexte plutôt que d’appliquer une politique unique à tout le parc applicatif d’une organisation. C’est la meilleure garantie d’éviter durablement les pièges du CSP.



