WordPress est solide, mais il a un point commun avec beaucoup de CMS populaires: sa surface d’attaque est vaste. Un plugin mal maintenu, un thème qui charge des scripts sans contrôle, une publicité ou un tracker mal configuré, et tout devient plus compliqué. La Content Security Policy (CSP) n’est pas une baguette magique, mais c’est un garde-fou très efficace contre les injections de contenu, notamment celles qui cherchent à exécuter du JavaScript dans le navigateur.
Dans la pratique, comprendre la CSP, ce n’est pas juste retenir une syntaxe. Il faut penser “ce que je veux autoriser, et ce que je veux refuser”, puis accepter que l’on va devoir ajuster au fil des thèmes, des plugins, et des intégrations. Je vais donc expliquer la logique, les exemples concrets, les erreurs fréquentes, et la méthode pour déployer une CSP sur WordPress sans casser votre site.
CSP, de quoi parle-t-on exactement
La CSP est un en-tête HTTP envoyé par votre serveur au navigateur. Le navigateur l’utilise ensuite comme un jeu de règles. Si votre politique dit “n’autorise ce type de script qu’à partir de ces origines”, alors le navigateur bloque tout ce qui ne respecte pas la règle.
Le bénéfice principal, c’est de réduire l’impact des failles XSS (Cross-Site Scripting) et de certaines formes d’injection. Même si un attaquant parvient à injecter du contenu dans une page, il lui sera beaucoup plus difficile de faire exécuter du code arbitraire, car le navigateur refuse les sources non prévues.
Autre intérêt, souvent sous-estimé: la CSP rend votre site plus “auditable” côté front. Quand votre politique est stricte, chaque script chargé devient un choix assumé. On comprend vite quels plugins ajoutent quels flux, et où se cachent les bricolages.
Les directives CSP à connaître (sans tout apprendre par cœur)
La CSP n’est pas une seule règle, c’est un ensemble de directives. Certaines contrôlent les scripts, d’autres les styles, les images, les polices, les formulaires, etc.
Pour WordPress, les plus importantes sont généralement:
- script-src pour les scripts JavaScript style-src pour les feuilles de style img-src pour les images font-src pour les polices connect-src pour les requêtes réseau (fetch, XHR, WebSockets) frame-src pour les iframes object-src pour le contenu type Flash ou plugins (aujourd’hui très marginal, mais la directive existe) base-uri pour les balises form-action pour contrôler où les formulaires peuvent envoyer leurs données
Il y a aussi des mécanismes très pratiques:
- nonce-... pour autoriser explicitement certains scripts inline, en leur donnant une valeur unique strict-dynamic qui, bien utilisée, peut simplifier l’autorisation des scripts chargés dynamiquement par un script autorisé report-uri et la variante moderne report-to pour envoyer des rapports quand quelque chose est bloqué
Sur un site WordPress “classique”, la plupart des réglages CSP finissent par tourner autour de script-src, style-src, et img-src, puis s’étendent vers connect-src quand on constate des erreurs réseau.
Pourquoi WordPress rend la CSP plus délicate que sur un site “full custom”
Un site WordPress, c’est rarement un front fermé. Vous avez:
1) des thèmes et des builders (Gutenberg, Elementor, WPBakery, etc.)
2) des plugins SEO, analytics, cache, sécurité, popups, formulaires, gestion des cookies 3) des bundles front parfois injectés en inline 
Résultat: si vous imposez une CSP trop stricte d’un coup, vous risquez de casser des fonctionnalités. Souvent ce n’est pas un “gros plantage” immédiat, c’est plus sournois: un bouton ne répond plus, un tracking ne se déclenche pas, une popup n’ouvre plus, un formulaire affiche une erreur discrète.
La méthode recommandée n’est donc pas “copier-coller une CSP parfaite”. Le bon réflexe consiste à déployer en mode “observation” d’abord, puis à serrer progressivement.
Le mode “report-only” et l’approche par étapes
La CSP existe en deux variantes utiles:
- CSP “enforcement”: le navigateur bloque directement ce qui viole la politique CSP “report-only”: le navigateur n’empêche rien, mais envoie des rapports quand une violation est détectée
Pour un WordPress existant, je privilégie presque toujours la seconde approche. Vous partez d’une politique raisonnable, vous observez 1 à 7 jours (selon la taille du trafic et le nombre de pages), puis vous durcissez.
Le piège classique, c’est de croire que “si je ne vois rien dans les rapports, tout va bien”. Parfois les rapports sont filtrés, le mécanisme de reporting n’est pas configuré côté serveur, ou certains navigateurs ne rapportent pas comme on l’attend. Mais globalement, le report-only est le meilleur compromis pour éviter des effets immédiats.
Construire une CSP: le cœur de la politique
Le point de départ le plus fréquent est une politique qui fixe une base “par défaut”, puis autorise plus finement.
En pratique, vous commencez souvent avec:
- default-src 'self' pour dire “par défaut, n’autorise que depuis le même domaine” puis vous ajoutez les directives spécifiques: script-src, style-src, img-src, etc.
Cette approche réduit les oublis. Si un plugin charge une ressource quelque part, elle sera bloquée et vous verrez rapidement des traces de violation.
Ensuite, vous ajoutez ce qui est légitimement nécessaire. Par exemple, si vous utilisez un CDN d’images, img-src devra inclure cette origine. Si vous chargez des scripts de tracking, script-src devra les inclure, ou bien vous devrez passer par un mécanisme de nonces pour limiter l’inline.
Nonce: utile, mais pas gratuit
Une nonce est une valeur unique, ajoutée à la directive CSP et reprise dans le tag
Le problème, c’est que sur WordPress, beaucoup de scripts inline proviennent de plugins, de thèmes ou de scripts générés côté PHP sans contrôle fin sur la nonce. Vous pouvez parfois adapter le front via un plugin CSP spécialisé, ou via une couche de personnalisation. Mais sur un site hérité, la nonce demande un minimum de travail. Le gain est énorme, mais il faut l’implémenter correctement, sinon vous aurez une CSP qui bloque tout, et vous perdrez le bénéfice.
Le compromis “unsafe-inline” et pourquoi je l’évite
On voit parfois des CSP avec script-src 'self' 'unsafe-inline'. Cela autorise quasiment l’injectabilité par inline. Cela peut permettre de faire fonctionner un site rapidement, mais ce n’est pas une protection réaliste contre les XSS via scripts inline. Si votre objectif est la sécurité, je considère unsafe-inline comme une étape transitoire, pas comme une fin.
Idem pour unsafe-eval. Je l’évite aussi. Beaucoup de bundlers récents n’en ont pas besoin en production, et les erreurs liées à eval peuvent signaler des composants mal configurés.
Exemples concrets adaptés à des scénarios WordPress
Plutôt que de vous donner “LA” CSP universelle, je vais montrer comment raisonner sur des cas typiques.
Cas 1: site vitrine simple, peu de scripts tiers
Si votre site charge essentiellement du WordPress, quelques styles, des images locales, et un analytics “standard”, vous pouvez viser une CSP assez stricte.
Le schéma mental est:
- default-src 'self' script-src 'self' + votre domaine analytics si nécessaire style-src 'self' + éventuellement votre domaine CDN de styles img-src 'self' + CDN images et data si nécessaire (attention à data:) connect-src vers analytics si vous utilisez des appels réseau bloquer implicitement object-src si vous n’utilisez pas de plugins
Dans ce scénario, vous allez probablement rencontrer des violations liées aux scripts inline. Si votre thème ou un plugin injecte des petits blocs inline, vous devrez soit les autoriser via un mécanisme compatible (nonce si possible), soit accepter une règle transitoire.
Cas 2: vous utilisez des polices via Google Fonts ou équivalent
Les polices sont un classique. Le navigateur va refuser les polices si font-src n’autorise pas l’origine.
Si vous utilisez Google Fonts, la directive font-src doit inclure le domaine correspondant. Selon votre configuration (CSS chargé depuis Google, polices chargées depuis un domaine dédié), les origines exactes peuvent varier. Là encore, les rapports CSP sont précieux, car ils vous donnent la provenance de la ressource bloquée.
Une stratégie pragmatique consiste à rester au plus strict avec font-src, plutôt que d’ouvrir plus largement default-src. C’est un endroit où on peut rapidement obtenir une CSP crédible.
Cas 3: page qui affiche des contenus embed, iframes, ou vidéos externes
Les iframes ont besoin de frame-src. Beaucoup de plugins de médias ou de “social embeds” ajoutent des iframes vers des plateformes tierces.
Si vous oubliez frame-src, vous verrez des cadres bloqués. C’est parfois visible immédiatement, parfois seulement après clic sur un bouton “afficher la vidéo”. Les rapports vous aideront à identifier l’origine à ajouter.
Cette fois, je recommande une approche par origine: vous autorisez uniquement les domaines qui hébergent réellement vos embeds, pas des wildcard trop larges.
Où intégrer la CSP sur WordPress
Sur un WordPress, la CSP peut être appliquée à plusieurs niveaux:
- au niveau serveur (Nginx, Apache) via des directives d’en-têtes via le serveur applicatif (reverse proxy, load balancer) via le fichier de configuration du plugin de cache (parfois possible) via un plugin WordPress qui ajoute l’en-tête CSP
Le choix dépend beaucoup de votre hébergement.
Niveau serveur, l’option la plus “propre”
Quand vous contrôlez Nginx ou Apache, vous pouvez mettre la CSP directement dans la configuration et être sûr qu’elle arrive au navigateur de façon fiable. C’est aussi plus simple à maintenir à long terme, surtout si vous voulez appliquer la même politique à toutes les pages.
Attention, toutefois: si vous utilisez un mode cache qui rend le HTML, il faut s’assurer que l’en-tête CSP n’est pas écrasé. Certains setups de cache ou WAF ajoutent leurs propres en-têtes, et vous pouvez vous retrouver avec deux CSP, ce qui rend l’effet plus complexe.
Plugin WordPress: pratique, mais à cadrer
Un plugin CSP peut être utile si vous ne touchez pas à la config serveur. Il peut aussi gérer des nonces, et parfois des exceptions par type de ressource.
Le risque, c’est l’accumulation de couches: un plugin CSP, un autre plugin sécurité, un WAF, et un plugin cache, tous peuvent finir par modifier les en-têtes. J’ai vu des cas où l’on croyait avoir une CSP “A”, mais une autre couche injectait “B”, et le navigateur appliquait la dernière reçue. Pour éviter ça, vérifiez toujours la CSP réellement envoyée dans les DevTools réseau.
Tester sans casser: méthodes terrain
La CSP se teste mieux dans deux endroits: dans le navigateur (DevTools) et dans vos logs ou rapports.
Dans Chrome ou Firefox, ouvrez l’onglet Réseau, inspectez l’en-tête Content-Security-Policy ou Content-Security-Policy-Report-Only, et regardez les erreurs dans la console. Quand quelque chose est bloqué, le message indique souvent la directive concernée et la ressource.

Une autre source utile: les rapports CSP. En mode report-only, configurez un endpoint qui collecte les violations. Ensuite, sur une période de test, vous identifiez les origines à ajouter.
J’ai aussi une règle personnelle: ne durcissez pas sur tout le site à la fois. Si vous avez des pages de formulaire, des landing pages, des pages d’admin ou des pages de checkout, commencez par des zones moins sensibles côté UX, puis élargissez.
Les problèmes fréquents (et comment les gérer)
1) Tout se bloque d’un coup
Cela arrive quand la politique n’autorise aucun script inline, alors que votre thème ou vos plugins s’appuient sur eux. Le symptôme le plus courant est une page blanche ou une interface cassée.
La correction passe rarement par “ouvrir tout”. Elle passe plutôt par une lecture attentive des violations. Commencez par script-src. Identifiez les scripts bloqués, puis décidez si vous pouvez:

- autoriser un domaine externe nécessaire remplacer un mécanisme inline par une alternative utiliser une nonce si le plugin/le thème le permet
Si vous êtes coincé sur un plugin qui injecte inline sans contrôle, vous pouvez temporairement assouplir votre politique pour ce site, puis planifier la migration. La sécurité, c’est aussi de savoir quand vous êtes dans une dette technique.
2) Les styles disparaissent
Les feuilles de style viennent souvent de plusieurs origines, notamment quand un plugin charge des CSS en ligne ou depuis un CDN.
Le symptôme: le HTML s’affiche, mais le site ressemble à une page non stylée. Le navigateur bloque parfois les styles si style-src n’autorise pas unsafe-inline ou le domaine CDN.
Je recommande d’éviter unsafe-inline en style si vous visez la sécurité. Mais là encore, dans l’existant, vous pouvez faire une transition contrôlée, surtout si vous utilisez beaucoup de CSS inline, par exemple dans certains builders.
3) Analytics et tracking cassent silencieusement
Souvent, les erreurs ne “cassent pas” la page, elles cassent seulement des événements. Vous constatez moins de conversions, ou un tableau de bord qui ne se met plus à jour.
C’est pour ça que je conseille de tester avec des scénarios utilisateur concrets: soumettre un formulaire, cliquer sur un bouton, parcourir une page typique, ouvrir une modale. Ensuite, regardez la console et les rapports CSP.
Quand vous ajoutez des origines dans connect-src ou script-src, vous réparez progressivement sans ouvrir au hasard.
4) Les exceptions finissent par proliférer
On autorise un domaine, puis un sous-domaine, puis un autre, puis on finit avec une CSP large qui n’apporte plus beaucoup. Je l’ai déjà vécu sur des sites qui grandissent vite, surtout avec des plugins “marketing”.
La bonne discipline: documenter ce que vous autorisez. Même une note interne suffit: “ce domaine sert à X, ce plugin a besoin de Y”. Et si un plugin est remplacé, vous supprimez l’autorisation correspondante.
La CSP est un contrat entre votre site et le navigateur. Un contrat trop flou perd sa valeur.
CSP et sécurité WordPress: limites et cohérence
La CSP renforce la sécurisation WordPress, mais elle ne remplace pas:
- un durcissement du serveur (mises à jour, permissions, configuration TLS) la réduction de surface via plugins minimum la prévention des injections côté serveur (sanitization, escaping, validation) une politique de cookies cohérente (HttpOnly, Secure, SameSite)
Si votre WordPress est vulnérable côté backend et que l’attaquant peut prendre le contrôle, la CSP ne peut pas “réparer” une exécution serveur compromise.
En revanche, si votre objectif est de limiter les impacts d’une XSS ou d’une injection dans une page, la CSP est une barrière très utile, surtout si elle est déployée progressivement vers quelque chose de strict.
Une méthode de déploiement réaliste sur un site WordPress existant
Voici une approche pragmatique qui marche dans beaucoup de cas, même quand l’existant est imparfait.
Phase 1: mettre en place une CSP “report-only” utile
Vous partez d’une politique qui réduit le risque, sans empêcher le site. Le but est de collecter des violations “réelles”. C’est plus rapide que de deviner.
Vous pouvez commencer avec default-src 'self' et compléter script-src, style-src, img-src. Puis vous laissez tourner.
Phase 2: corriger, ajouter, puis durcir
À partir des rapports, vous ajoutez uniquement les origines réellement nécessaires. Pour les inline, vous explorez les possibilités de nonce ou d’ajustement des plugins. Sinon, vous acceptez des compromis temporaires.
Quand le site semble stable, vous passez en enforcement, même partiel si vous pouvez le faire (ou via une politique appliquée à certaines routes).
Phase 3: rendre la politique plus stricte
Une fois stable, vous supprimez les assouplissements temporaires. C’est souvent le moment le plus utile pour la sécurité. Les compromis sont la zone grise, et c’est là que la CSP peut vraiment faire la différence.
Voici une mini check-list, pour garder le cap sans se noyer:
Vérifier l’en-tête CSP réellement reçu dans les DevTools, pas ce que vous pensez avoir configuré Activer report-only pendant une période de test représentative Tester des parcours utilisateurs, pas seulement le chargement initial Documenter chaque origine ajoutée, pour pouvoir la retirer plus tard Passer en enforcement seulement quand la page critique ne logge plus de violations majeuresExemple de politique “base” à adapter (structure, pas recette)
Je vais rester volontairement descriptif, car une CSP “copiée-collée” a de fortes chances de casser quelque chose dans votre stack. En revanche, la structure type ressemble à ceci:
- default-src 'self' script-src avec self et des origines pour analytics, éventuellement CDN si vos scripts viennent de là style-src avec self et les origines pour vos CSS img-src avec self et les CDNs images utilisés connect-src pour les appels réseau de vos services object-src 'none' si vous n’utilisez pas d’objets plugins
Ensuite, vous ajoutez les directives frame-src si vos embeds existent, et vous ajustez.
L’important n’est pas la liste exacte d’origines, mais la discipline: chaque directive cible ses ressources, et vous évitez d’ouvrir “par défaut” plus large que nécessaire.
Nonce vs hash vs wildcard: choisir avec bon sens
On rencontre trois approches pour autoriser des scripts inline.
- nonce: robuste, mais demande une intégration front qui sait injecter la nonce au bon endroit hash: fonctionne si le contenu inline est stable et connu, et si vous pouvez générer le hash côté config wildcard ou unsafe: simple, mais cela ouvre beaucoup trop
Sur WordPress, le hash est rarement simple sur un site vivant, car les scripts inline peuvent changer d’une page à l’autre ou à chaque déploiement. Les nonces sont souvent la direction à privilégier quand vous voulez du inline autorisé, mais encore une fois, il faut que vos thèmes et plugins puissent s’y prêter.
Le bon “bon sens opérationnel” que j’utilise est le suivant: si un plugin injecte beaucoup de inline et ne propose pas de manière nonce-friendly, je préfère limiter l’assouplissement à ce composant, puis migrer ou remplacer. Faire une CSP parfaite avec une intégration non compatible, c’est souvent une impasse.
Le reporting CSP: interpréter sans se tromper
Les rapports CSP vous disent quelles ressources sont bloquées. Mais ils ne vous disent pas toujours pourquoi votre politique est mal formulée ou trop stricte. Deux erreurs arrivent souvent:
- Vous ajoutez une origine au hasard pour “faire disparaître” les erreurs, et vous ouvrez plus que nécessaire Vous supposez que si une ressource n’est pas bloquée, elle est sûre. En réalité, la CSP n’évalue pas le contenu, elle contrôle la source. La sécurité dépend aussi du reste de votre système
Quand vous corrigez, partez de la violation principale. Par exemple, si c’est script-src qui déclenche tout, commencez par là. Une fois script-src corrigé, les autres violations peuvent se calmer d’elles-mêmes, car certains scripts ne s’exécutent plus et donc ne déclenchent pas des chargements ultérieurs.
Comparaison rapide: enforcement vs report-only
Pour décider quand basculer, gardez cette grille en tête:
| Approche | Ce que vous gagnez | Risque principal | |---|---|---| | report-only | observer sans casser le site | oublier que les rapports manquent parfois selon les navigateurs ou la config | | enforcement | bloquer réellement les violations | casser des fonctionnalités si la politique est trop stricte | | approche progressive | une montée en sécurité réaliste | demander du temps de validation sur des parcours réels |
En pratique, l’approche progressive est celle qui m’a le plus souvent évité des retours utilisateurs, surtout sur des sites avec beaucoup de plugins.
Edge cases WordPress à surveiller
Quelques cas reviennent régulièrement:
- pages d’admin et écrans de connexion: certains assets sont chargés différemment pages WooCommerce: scripts de checkout, widgets de paiement, et appels réseau spécifiques cache et minification: un plugin d’optimisation peut regrouper des scripts et modifier la façon dont ils sont chargés, ce qui change la CSP nécessaire chargement différé d’assets: un script “plus tard” peut déclencher des erreurs une fois qu’on scrolle, pas au chargement initial balises “inline” générées par les builders: elles posent souvent le plus de problèmes pour un CSP stricte
Sur ces cas, la meilleure méthode reste la même: vérifier ce qui se charge réellement, au bon moment. Si vous ne testez qu’une page “homepage”, vous découvrirez les problèmes le jour où un utilisateur utilisera une fonctionnalité moins fréquentée.
Et si vous ne pouvez pas imposer CSP partout ?
Dans certains environnements (multi-sites, hébergement mutualisé, contraintes de WAF), vous pouvez ne pas appliquer la même CSP à toutes les routes. Dans ce cas, vous ciblez d’abord ce qui a le plus de valeur:
- pages publiques exposées (articles, pages statiques) pages qui reçoivent des interactions (commentaires, formulaires) pages où vous utilisez des scripts tiers
L’objectif n’est pas d’avoir une CSP uniforme “parfaitement identique”. L’objectif est d’avoir une CSP qui réduit le risque sur les zones les plus sensibles, et d’éliminer progressivement les exceptions.
Une dernière règle: mesurez, puis simplifiez
Une CSP qui marche n’est pas forcément une CSP qui protège le mieux. Beaucoup de sites finissent avec une politique qui ressemble à une liste de domaines cumulés, parce qu’on a ajouté au fil des problèmes.
La stratégie la plus saine sur 30 à 90 jours, c’est de:
- mesurer les violations restantes retirer les plugins qui ne servent plus remplacer les intégrations qui poussent trop d’exceptions serrer les directives une par une, en commençant par celles qui contrôlent l’exécution (scripts, puis styles)
C’est long, oui. Mais c’est aussi là que la sécurisation WordPress gagne en maturité. La CSP devient un outil de pilotage, pas un bricolage final.
Si vous me donnez votre configuration (hébergement, Cloudflare ou équivalent, principaux https://gardewp.fr/securite-wordpress/ plugins, services tiers, usage de Google Fonts, présence de WooCommerce et de builders), je peux vous proposer une CSP de départ cohérente, en mode report-only, et une méthode de durcissement adaptée à votre cas, sans casser les fonctionnalités essentielles.