Content Security Policy stricte sur un site marketing en 2026 : faisable, voici comment
Nouh Benzidane · 10 min de lecture En résumé
Oui, une Content Security Policy stricte tient sur un site vitrine sans rien casser. L'en-tête exact que je déploie, le seul compromis que je garde, la méthode sans risque.
Oui, une Content Security Policy stricte sur un site marketing est faisable, et je la déploie sur la quasi-totalité de mes livraisons. La croyance répandue selon laquelle une CSP « casse tout » vient presque toujours d’un copier-coller d’en-tête trop agressif sur une stack qui n’était pas prête. Posée correctement, sur un site statique bien construit, elle ne coûte rien en performance, rien en maintenance, et elle ferme une famille entière d’attaques.
Ce site, nouhbenzidane.fr, sert exactement l’en-tête que je vais détailler. Je l’ai aussi déployé sur urgenceserrures.fr et plombiersidf.fr. Voici la politique exacte ligne par ligne, le seul compromis que j’assume et pourquoi il n’est pas le trou de sécurité qu’on imagine, puis la méthode de déploiement qui évite de casser la prod.
Ce qu’une CSP protège réellement
La Content Security Policy est un en-tête HTTP qui dit au navigateur, de façon déclarative, quelles ressources il a le droit de charger et exécuter. Concrètement, elle répond à une seule question répétée pour chaque ressource : « ce script, cette image, cette police, ce formulaire vient-il d’une origine que j’autorise ? » Tout ce qui n’est pas explicitement autorisé est bloqué par le navigateur lui-même, avant exécution.
Le gain principal est la défense contre le cross-site scripting (XSS), c’est-à-dire l’injection de code malveillant dans une page. Comme le détaille la documentation web.dev sur la CSP stricte, même si un attaquant parvient à glisser un <script> dans votre HTML, une politique bien posée empêche son exécution parce que l’origine n’est pas autorisée. La CSP n’est pas une protection contre l’injection, c’est une seconde ligne qui neutralise l’injection si elle arrive.
Les autres bénéfices sont concrets et souvent sous-estimés. La directive frame-ancestors 'none' interdit qu’un tiers vous affiche dans une iframe, ce qui bloque le clickjacking. La directive form-action 'self' empêche qu’un formulaire injecté envoie ses données vers un serveur pirate. La directive upgrade-insecure-requests force chaque sous-ressource en HTTPS. Pour un site qui collecte des leads via un formulaire de devis, ce ne sont pas des abstractions : c’est la différence entre un formulaire qui poste chez vous et un formulaire détourné qui poste chez quelqu’un d’autre.
L’en-tête exact que je sers en production
Voici la politique appliquée à chaque page HTML de ce site, telle qu’elle figure dans ma configuration Netlify :
Content-Security-Policy:
default-src 'self';
script-src 'self' 'unsafe-inline' https://plausible.io;
style-src 'self' 'unsafe-inline';
img-src 'self' data: https:;
font-src 'self' data:;
connect-src 'self' https://plausible.io;
frame-ancestors 'none';
frame-src 'none';
object-src 'none';
base-uri 'self';
form-action 'self';
upgrade-insecure-requests
Chaque directive a une raison d’être que je peux justifier en une phrase :
default-src 'self'pose la règle par défaut : rien ne se charge en dehors de mon propre domaine, sauf exception explicite ci-dessous.script-srcautorise mes scripts, les bootstraps inline d’Astro et un seul script tiers, Plausible, déclaré par son origine.style-srcautorise les styles inline parce que la bibliothèque d’animation Motion écrit des attributs de style à chaque frame d’animation.img-srccouvre mes images, les data-URIs et les vignettes distantes en HTTPS.connect-src 'self' https://plausible.ioverrouille les requêtes réseau sur mon origine et l’analytics, rien d’autre ne peut exfiltrer de données.object-src 'none'etframe-src 'none'bannissent purement et simplement<object>,<embed>et<iframe>, des vecteurs d’attaque que je n’utilise jamais sur une vitrine.base-uri 'self'empêche le détournement de la balise<base href>, une astuce classique pour réécrire toutes les URLs relatives d’une page.
À côté de la CSP, je sers toujours le trio habituel : Strict-Transport-Security avec un max-age d’un an (31536000 secondes) et preload, X-Content-Type-Options: nosniff, et une Permissions-Policy qui coupe caméra, micro, géolocalisation et le ciblage publicitaire de Google via interest-cohort=() et browsing-topics=(). Sur un audit securityheaders.com, cet ensemble sort un A. Mais la note n’est pas le but, c’est un effet de bord d’une configuration honnête.
Le seul compromis : unsafe-inline, et pourquoi je l’assume
Le puriste de la sécurité va tiquer sur le 'unsafe-inline' dans mon script-src. Il a raison sur le principe et tort sur le cas précis. Voici l’arbitrage exact, parce que la transparence vaut mieux qu’une fausse note A+.
Astro injecte de petits scripts inline pour hydrater les îlots React des composants interactifs (les directives client:idle, client:visible, client:load). Sans 'unsafe-inline', ces îlots ne s’hydratent jamais, les animations Motion restent figées à opacity:0, et le hero de la page reste blanc. La parade canonique est la CSP par hash : Astro peut hasher chaque script inline et n’autoriser que ces empreintes. Le problème est qu’Astro hashe aussi le style-src, ce qui casse Motion qui mute les styles inline en continu. Le moindre bump de version d’Astro ou la moindre édition d’un script inline change le hash et casse le site en silence en production.
Alors je garde 'unsafe-inline', en connaissance de cause, et voici pourquoi le risque résiduel est nul en pratique. Le 'unsafe-inline' n’est dangereux que s’il existe une faille d’injection à exploiter, c’est-à-dire un endroit où un attaquant peut faire écrire son <script> dans ma page. Or ce site ne rend aucun contenu utilisateur en HTML : pas de commentaires, pas de profils, pas de recherche réfléchie, pas de Markdown tiers rendu sans assainissement. Le seul flux entrant est le formulaire de devis, qui poste vers Netlify et ne réinjecte jamais ses données dans une page. Il n’y a tout simplement pas de point d’injection où un script malveillant pourrait atterrir. Le 'unsafe-inline' protège une porte qui n’existe pas.
La règle que j’applique chez mes clients est nette. Site statique sans contenu utilisateur en HTML : 'unsafe-inline' reste acceptable, parce qu’il n’y a pas de surface XSS. Site qui affiche du contenu utilisateur, des avis, un forum, un champ de recherche, du HTML tiers : alors la CSP stricte avec nonce et strict-dynamic devient non négociable, et on accepte le surcoût de build. Le contexte décide, pas le dogme.
Déployer sans casser la prod : le mode Report-Only
L’erreur qui donne à la CSP sa mauvaise réputation, c’est de poser l’en-tête bloquant directement en production et de découvrir les violations quand un visiteur signale un bouton mort. La méthode propre passe par un en-tête jumeau : Content-Security-Policy-Report-Only.
Cet en-tête applique la même politique mais ne bloque rien : il journalise chaque violation dans la console du navigateur et, si vous configurez une report-uri ou report-to, vers un point de collecte. Le déploiement se fait alors en quatre temps que je suis systématiquement :
- Poser la politique en mode
Report-Onlyavec les directives serrées que vous visez. - Naviguer sur l’intégralité du site, sur mobile et desktop, en ouvrant la console : chaque ressource bloquée par la future politique remonte une violation.
- Trier les violations. Une ressource légitime oubliée (une police, un domaine d’analytics) se corrige en élargissant la directive concernée. Une violation suspecte révèle souvent un script tiers dont vous ignoriez l’existence.
- Une fois la liste de violations vide sur un parcours complet, renommer l’en-tête en
Content-Security-Policybloquant et redéployer.
Sur une stack statique comme Astro déployée sur Netlify, tout ceci tient dans le fichier netlify.toml, dans un bloc [[headers]] appliqué à /*. Aucun code applicatif n’est touché, l’en-tête est ajouté par le CDN à la volée. Pour valider le résultat, je passe la politique dans le CSP Evaluator de Google et dans Mozilla Observatory, qui pointent les directives trop laxistes et les oublis classiques comme l’absence de object-src 'none'.
La CSP est aussi un argument RGPD
Un dernier point que les décideurs sous-estiment. En France, l’article 32 du RGPD impose au responsable de traitement des mesures techniques appropriées pour garantir la sécurité des données personnelles. Dès qu’un site héberge un formulaire de contact ou de devis, il traite des données personnelles, et la sécurité de ce traitement devient une obligation légale, pas une option de confort.
La CNIL, dans son guide de la sécurité des données personnelles, range explicitement les en-têtes de sécurité HTTP parmi les mesures attendues. Une CSP n’est donc pas qu’une bonne pratique d’ingénieur : c’est un élément du faisceau de mesures qu’un contrôle attend de voir sur un site qui collecte des leads. Quand je livre un site vitrine avec formulaire, la CSP fait partie du périmètre de conformité au même titre que le chiffrement HTTPS et la minimisation des données collectées. Elle ne coûte rien et elle documente votre sérieux.
La réponse, sans détour
Une Content Security Policy stricte sur un site marketing est non seulement faisable, c’est devenu une base que je pose par défaut. L’en-tête tient dans une ligne de configuration, n’ajoute aucune latence, et bloque le XSS, le clickjacking et l’exfiltration de données vers un domaine tiers. Le seul compromis réel, le 'unsafe-inline' sur le script-src, n’est un risque que si le site rend du contenu utilisateur en HTML ; sur une vitrine statique sans surface d’injection, il protège une porte inexistante. Pour les sites qui affichent du contenu tiers, on passe au nonce avec strict-dynamic et on assume le surcoût. La bonne méthode de déploiement n’est jamais le copier-coller en production : c’est le mode Report-Only, qui journalise les violations sans rien casser, jusqu’à une liste vide. Et en France, avec l’article 32 du RGPD, cette mesure cesse d’être facultative dès le premier formulaire de devis.
Ce qu’il faut retenir
- Une CSP est un en-tête HTTP de quelques centaines d’octets, sans coût de performance, qui neutralise le XSS, le clickjacking et l’exfiltration de données.
- Sur une stack statique comme Astro sur Netlify, la politique se pose dans un bloc
[[headers]]dunetlify.toml, sans toucher au code applicatif. - Le
'unsafe-inline'sur lescript-srcreste défendable pour un site sans contenu utilisateur en HTML, parce qu’il n’existe alors aucune faille d’injection à exploiter. - Un site qui affiche des avis, un forum ou du HTML tiers doit passer à une CSP avec
nonceetstrict-dynamic, pas de compromis possible. - Déployez toujours d’abord en
Content-Security-Policy-Report-Onlypour journaliser les violations, puis basculez sur l’en-tête bloquant une fois la liste vide. - L’article 32 du RGPD impose des mesures de sécurité appropriées : dès qu’un formulaire collecte des données, la CSP devient un élément attendu de votre conformité.
/faq
Questions fréquentes
Une CSP est-elle obligatoire pour un site vitrine en France ?
Aucun texte n'impose nommément une Content Security Policy. Mais l'article 32 du RGPD exige des mesures techniques appropriées pour sécuriser les traitements de données personnelles, et la CNIL recommande les en-têtes de sécurité dans son guide. Dès que votre site contient un formulaire de contact ou de devis, vous traitez des données personnelles, et une CSP fait partie des mesures raisonnables qu'un contrôleur attend de voir.
Une CSP ralentit-elle le site ?
Non. C'est un simple en-tête HTTP de quelques centaines d'octets envoyé par le serveur ou le CDN. Il n'ajoute aucun script, aucune requête, aucun blocage de rendu. Sur mes livraisons, l'en-tête n'a jamais coûté un millième de seconde mesurable sur le Largest Contentful Paint.
Faut-il une CSP stricte avec 'unsafe-inline' ou avec des nonces ?
Pour un site marketing statique qui n'affiche aucun contenu utilisateur en HTML, une CSP avec 'unsafe-inline' sur le script-src reste défendable, parce qu'il n'existe aucune faille d'injection à exploiter. Le strict-dynamic avec nonce est plus sûr en théorie, mais il complique le build et casse facilement à chaque mise à jour. Je le réserve aux sites qui rendent du contenu tiers ou des entrées utilisateur.
Comment déployer une CSP sans casser le site en production ?
Commencez par la version Content-Security-Policy-Report-Only, qui journalise les violations sans rien bloquer. Naviguez sur tout le site, lisez la console et les rapports, ajustez les directives jusqu'à zéro violation légitime, puis basculez sur l'en-tête bloquant. Cette phase d'observation évite l'angle mort classique du formulaire ou de l'iframe oublié.
/sources
- [1] MDN Web Docs - Content-Security-Policy (consulté le 2026-06-11)
- [2] W3C - Content Security Policy Level 3 (consulté le 2026-06-11)
- [3] web.dev - Mitigate cross-site scripting (XSS) with a strict Content Security Policy (consulté le 2026-06-11)
- [4] OWASP - Content Security Policy Cheat Sheet (consulté le 2026-06-11)
- [5] CNIL - La sécurité des données personnelles (consulté le 2026-06-11)
/à lire ensuite
Continuer la lecture
-
seo
llms.txt : pourquoi et comment l'implémenter sur un site en 2026
llms.txt est un fichier Markdown à déposer à la racine de votre site pour guider ChatGPT, Claude et Perplexity. Format exact, implémentation sur Astro et WordPress, position RGPD.
-
sites internet
Migrer un site WordPress vers Astro sans casser le référencement
Refondre un WordPress lent en site Astro statique tout en préservant le SEO acquis. Méthode pas-à-pas, mapping des redirections 301, vérifications post-migration, retour terrain sur un cas réel.
-
securite
Pas de bandeau cookies sans risque RGPD : la doctrine CNIL 2026
Un site sans bandeau cookies peut être parfaitement conforme au RGPD. La condition est simple, la doctrine CNIL est claire, et ce qui change au 1er janvier 2026 rend le choix encore plus net.