Sécurité WordPress : configurer correctement les headers de sécurité

Les headers de sécurité, ce sont ces en-têtes HTTP que votre serveur envoie au navigateur pour réduire certaines classes de risques. Sur un site WordPress, ils servent surtout à limiter l’impact des ici erreurs de configuration, des contenus injectés, et des comportements inattendus côté navigateur. Le piège, c’est de croire qu’une liste d’en-têtes suffit. En pratique, la configuration dépend de votre stack (Apache ou Nginx, CDN éventuel, reverse proxy, thème, plugins, tracking, éventuels formulaires intégrés), et certains en-têtes peuvent casser une fonctionnalité si on les active sans réflexion.

J’ai vu des sites passer de “tout va bien” à “pages blanches” après une politique CSP trop stricte, simplement parce qu’un script chargé depuis un domaine de tracking avait changé. À l’inverse, j’ai aussi vu des sites “couverts” par CSP, mais sans HSTS, et exposés à des failles qui n’ont rien à voir avec la CSP.

L’objectif ici est simple: comprendre les headers essentiels, les configurer correctement selon votre contexte, puis les valider sans aveuglement.

Pourquoi les headers changent vraiment la donne

Les headers ne remplacent pas WordPress, ni le durcissement du serveur, ni la protection applicative. Ils viennent en renfort, au niveau du navigateur.

Par exemple:

    Une Content Security Policy (CSP) peut empêcher l’exécution de scripts injectés, même si un attaquant parvient à déposer du contenu malveillant. X-Frame-Options ou frame-ancestors dans CSP limitent les tentatives d’overlay de type clickjacking. Strict-Transport-Security (HSTS) force le navigateur à utiliser HTTPS, ce qui réduit les risques liés aux connexions non chiffrées et aux redirections. X-Content-Type-Options aide à éviter certains scénarios où le navigateur interprète un type de fichier de manière non souhaitée.

Le point important est la logique “réduction d’impact”. Les headers agissent comme une barrière de sécurité supplémentaire lorsque le reste du système n’est pas parfait. Ils ne rendent pas votre site invulnérable, mais ils évitent que les conséquences deviennent catastrophiques.

Renforcer sécurité WordPress passe souvent par une approche en couches. Les headers font partie de cette couche côté navigateur, avec un bénéfice réel quand ils sont bien réglés.

Avant de modifier: cartographier ce qui charge votre site

Avant même de toucher à la moindre ligne dans .htaccess ou dans votre configuration Nginx, prenez deux minutes pour identifier ce qui peut influencer vos headers. La CSP en particulier est sensible aux origines (domaines) de:

    scripts (thème, plugins, scripts de tracking, scripts d’analyse), styles (CSS de certains plugins ou frameworks), polices (Google Fonts et équivalents), images (CDN, domaines d’avatars, widgets), iframes (lecteurs vidéo, formulaires intégrés), formulaires et endpoints externes.

Concrètement, ouvrez votre site, puis regardez le trafic réseau dans l’onglet “Network” de votre navigateur. Notez les domaines externes qui apparaissent comme sources de scripts et de styles.

Ce travail est fastidieux une première fois, mais il évite le classique scénario: vous activez CSP “par principe”, et le site perd des fonctions parce qu’un domaine a été omis.

Mettre en place HSTS sans vous piéger vous-même

HSTS est un en-tête majeur: il indique au navigateur de n’utiliser que HTTPS pendant une durée donnée. L’enjeu, c’est que si vous mettez une valeur “trop engageante” alors que votre HTTPS n’est pas parfaitement stable, vous risquez de bloquer les retours en arrière.

Deux notions reviennent souvent:

max-age: combien de temps HSTS doit être respecté. includeSubDomains: s’applique-t-il à tous vos sous-domaines. preload: indique un comportement compatible avec l’inscription dans une liste globale. À éviter au début.

Sur WordPress, je recommande d’abord une approche progressive. Commencez par activer HSTS sur le domaine principal, avec une durée raisonnable, puis augmentez après stabilité.

Si vous utilisez un CDN ou un reverse proxy, vérifiez qui met réellement l’en-tête. Il arrive que le CDN ajoute ses propres headers et que votre config serveur n’ait pas l’effet attendu.

X-Frame-Options et clickjacking: simple, mais attention aux embeds

Le clickjacking survient quand un site est affiché dans un iframe sur une page malveillante. Pour limiter ça, vous avez deux approches:

    X-Frame-Options avec des valeurs comme DENY ou SAMEORIGIN ou frame-ancestors via CSP, qui est plus flexible.

Sur WordPress, la difficulté vient souvent d’un besoin légitime d’iframes: des outils intégrés, des checkouts, ou des lecteurs vidéo. Si votre site doit être intégrable dans certains contextes, un DENY pur peut bloquer des fonctionnalités.

Le choix dépend donc de votre politique produit:

    Votre site doit-il être “inframable” par des partenaires ou des plateformes ? Ou est-il strictement destiné à être affiché seul ?

Dans la plupart des cas “site vitrine” et “blog”, refuser l’iframe à tout le monde est acceptable. Dans des contextes d’intégration, il faut ajuster.

CSP: la pièce la plus puissante, et aussi la plus fragile

La Content Security Policy est souvent l’en-tête qui apporte le plus de valeur. Elle peut empêcher l’exécution de scripts hors des origines autorisées et encadrer les sources de ressources.

Mais CSP demande une méthode. Le principal risque, c’est l’activation directe en mode “enforcement” alors que vous n’avez pas tout identifié: un script de plugin chargé depuis un domaine inattendu, un analytics qui change de chemin, une police, ou une ressource injectée par un composant tiers.

Une CSP bien construite est généralement composée de directives (une “grammaire” de règles). Les plus fréquentes:

    default-src (base) script-src (scripts) style-src (styles) img-src (images) font-src (polices) connect-src (requêtes XHR/fetch, souvent utile pour analytics et formulaires) frame-ancestors (anti iframe) form-action (où les formulaires peuvent envoyer) base-uri (contraintes sur les balises ) upgrade-insecure-requests (forcer les URLs http vers https, utile si vous avez des références non sécurisées) report-to et report-uri (collecte de rapports en mode test, selon compatibilités)

Je conseille de traiter la CSP comme un projet de durcissement progressif:

image

    d’abord une CSP en mode “apprentissage” (selon les mécanismes de rapport), ensuite un durcissement ciblé.

Dans beaucoup de cas, on part d’un socle minimal qui évite les scripts inline et les sources externes non maîtrisées. Puis on élargit les origines nécessaires.

Attention aux scripts inline et au “nonce” improvisé

WordPress et ses plugins injectent parfois du JavaScript inline. Si vous bannissez tout inline sans stratégie, vous risquez de casser le site. Les options typiques sont:

    autoriser les inline scripts via unsafe-inline (mauvaise idée sur un site exposé), ou mieux, utiliser des nonces générés côté serveur.

En environnement WordPress, le nonce est possible mais il faut une intégration propre. Selon votre setup (et vos plugins), ce n’est pas toujours trivial. Une approche prudente consiste à identifier les besoins inline réellement présents, puis à réduire progressivement sans tout casser.

Les headers “moins visibles” qui comptent

En dehors des grands classiques, il existe plusieurs en-têtes qui réduisent des risques de compatibilité navigateur ou de fuite d’informations.

Parmi ceux qui reviennent souvent sur des sites WordPress:

    X-Content-Type-Options: aide le navigateur à respecter les types déclarés, utile pour éviter certains interprétations ambiguës. Referrer-Policy: contrôle ce que votre site envoie comme en-tête Referer lors des navigations vers des domaines tiers. C’est un levier de réduction de fuite d’URL sensibles. Permissions-Policy: limite des API navigateur (géo, caméra, micro) si vous ne les utilisez pas. X-XSS-Protection: reste lié à des anciens mécanismes de protection. Selon les navigateurs, son utilité réelle est variable, donc je le traite plutôt comme un bonus de compatibilité qu’un pilier.

Le point important: ces headers doivent être cohérents avec vos besoins. Si votre site utilise un besoin réel de géolocalisation côté front, une Permissions-Policy trop restrictive casse l’expérience.

Où configurer ces headers sur WordPress: Apache, Nginx, CDN et plugins

Sur WordPress, plusieurs chemins existent pour ajouter des en-têtes. Dans la réalité, vous devez choisir celui qui correspond à votre architecture.

    Apache: souvent via .htaccess si vous avez le droit d’écrire, ou via la configuration de vhost. Nginx: via des directives add_header dans un server ou un bloc location. CDN / reverse proxy: certains fournisseurs vous permettent de définir headers au niveau du bord. Dans ce cas, c’est le CDN qui fait foi. Plugins de sécurité WordPress: pratique, mais parfois trop “générique”. Ils peuvent activer des politiques qui ne correspondent pas à vos domaines réels ou à votre CSP actuelle.

Mon conseil pragmatique: si vous passez par un CDN, commencez par vérifier si l’en-tête sort réellement dans les réponses HTTP finales. Ensuite seulement, ajustez côté serveur.

Un exemple de politique raisonnable (à adapter)

Les exemples “prêts à copier” sont souvent trompeurs, parce que chaque site a ses propres domaines et ses propres intégrations. Je vais quand même donner une base pour illustrer l’approche, pas pour la coller sans contrôle.

Une CSP orientée durcissement, sans être extrême, ressemble souvent à ceci en esprit:

    bannir les scripts par défaut non contrôlés, autoriser explicitement des origines de scripts (votre domaine, éventuellement des CDN dont vous dépendez), encadrer les images et les connexions, définir frame-ancestors pour limiter l’iframe.

Ensuite, vous ajustez script-src et style-src jusqu’à ce que votre site fonctionne.

Sur un site WordPress classique, le travail porte presque toujours sur script-src, style-src et connect-src. Si vous activez le reste sans les bons domaines, vous obtiendrez soit des erreurs console, soit des fonctionnalités cassées.

Vérifier que les headers sont bien présents, pas juste “déclarés”

Le bon réflexe consiste à valider ce que le navigateur reçoit réellement.

Ouvrez vos outils de développement, regardez “Network”, puis inspectez les réponses HTML et quelques ressources clés. Les en-têtes doivent être cohérents sur:

    la page d’accueil, une page de contenu, une page d’admin si vous l’exposez, et idéalement aussi sur les endpoints qui servent des réponses sensibles.

Pourquoi c’est important? Parce que parfois, l’en-tête est défini uniquement dans certains blocs de configuration, ou seulement sur des routes spécifiques. Le site “semble sécurisé”, mais une route particulière ne renvoie pas les headers.

Checklist courte avant d’activer CSP et HSTS en dur

Identifier les domaines externes réellement chargés (scripts, styles, images, frames, appels réseau). Activer HSTS avec une durée prudente d’abord, puis augmenter après stabilité. Construire la CSP en mode progression, éviter unsafe-inline comme solution par défaut. Valider sur plusieurs navigateurs et sur une session “qui ressemble à l’utilisateur réel” (pas uniquement votre cache local). Tester au moins une page qui charge le plus de plugins et une page “simple”.

Les pièges WordPress fréquents

1) “CSP cassée” après activation d’un plugin

Beaucoup de plugins chargent des scripts externes ou ajoutent des inline scripts. Le jour où vous mettez à jour ou installez un plugin, votre CSP peut devenir trop stricte. Un suivi régulier est nécessaire.

Ce que j’ai appris sur le terrain: dès qu’un plugin change, faites une revalidation ciblée de la console et des requêtes réseau. Une CSP qui “tenait” peut se mettre à bloquer une ressource sans que le site affiche une erreur claire.

2) Mise en cache qui masque les changements

Si vous avez un cache serveur ou CDN, vos headers peuvent être servis depuis l’ancienne version. Résultat: vous ajustez la config, mais vous voyez toujours l’ancienne politique. Il faut purger le bon cache, ou tester avec un navigateur sans cache, ou encore forcer la désactivation côté devtools.

3) Admin et front, deux réalités

Beaucoup de configurations traitent le front-end. Mais WordPress admin est une autre zone, avec ses scripts, ses comportements, parfois ses iframes, et sa tolérance à certaines sources. Une politique uniforme peut être trop dangereuse ou trop restrictive.

Vous pouvez décider de:

    appliquer une politique plus flexible à /wp-admin/, ou appliquer la même, mais alors vous devez être certain que tous les assets et scripts admin passent.

Dans l’approche “renforcer sécurité WordPress” la plus prudente, je traite admin et front séparément, au moins pour CSP et parfois pour d’autres headers.

Interactions avec WooCommerce, formulaires et paiements

Les sites avec e-commerce ajoutent une complexité: checkout, scripts de paiement, widgets, et redirections vers des domaines tiers. Là, une CSP trop stricte sur script-src ou frame-ancestors peut casser des étapes.

Le vrai travail n’est pas seulement de deviner les domaines. C’est de confirmer ce que le navigateur charge pendant:

    la liste produit, la page produit, l’ajout au panier, et surtout la page de checkout.

Même si vous avez une CSP fonctionnelle sur 80 pour cent des pages, les 20 pour cent restants peuvent être ceux qui impliquent des intégrations de paiement.

Un point sur les headers et la compatibilité

Les navigateurs interprètent les directives CSP avec des nuances, et certains headers sont plus utiles que d’autres selon les environnements. Il n’est pas nécessaire de chercher la “perfection universelle” si votre audience est majoritairement moderne.

Ce que je fais en général: je construis pour un fonctionnement solide, puis je surveille les erreurs de console et les rapports quand c’est possible. Quand un utilisateur signale un blocage, je le reproduis et je corrige la directive précise, plutôt que d’assouplir toute la politique.

Le compromis est sain: sécurité plus élevée, sans rendre le site inutilisable.

Tester et ajuster après déploiement

Une fois les headers en place, laissez le site vivre un peu, ou faites un test plus structuré avant la mise en production. L’idée est de repérer les erreurs typiques: “Refused to execute script…”, “Blocked by frame-ancestors…”, “Content type refused…”.

Voici une petite méthode de validation:

Ouvrir les pages clés en navigation privée, sans extension de sécurité qui pourrait masquer des erreurs. Contrôler la console pour les refus CSP et noter la directive impliquée. Vérifier dans l’inspecteur réseau que les en-têtes s’appliquent bien aux bonnes réponses.

Conclusion de terrain (sans slogans): construire une politique qui tient dans le temps

Configurer correctement les headers de sécurité sur WordPress, ce n’est pas “mettre une fois et oublier”. C’est un réglage continu entre sécurité et fonctionnement. CSP est la plus exigeante, HSTS la plus engageante, et le reste fait surtout gagner en robustesse lorsque le navigateur devient un rempart supplémentaire.

Si vous adoptez une méthode progressive, avec une validation réelle côté navigateur et une attention particulière aux plugins, vous pouvez renforcer sécurité WordPress de façon concrète, sans transformer votre site en chantier permanent.

Si vous me dites votre environnement (Apache ou Nginx, présence ou non d’un CDN, et quelques plugins critiques comme cache, formulaires, analytics, e-commerce), je peux aussi vous proposer une base de headers plus adaptée à votre cas, avec une approche de durcissement par étapes.