# En-têtes HTTP de sécurité sur WordPress : le complément indispensable au cœur

> CSP, HSTS, X-Frame-Options : ces en-têtes HTTP referment des failles que le cœur de WordPress ne peut pas traiter seul. Voici comment les mettre en place sans casser le site.

- Auteur : Clément Hadrot
- Publié le : 2022-06-21
- Mis à jour le : 2022-06-21
- Catégorie : Sécurité
- URL : https://wpmoderne.dev.wordpress-developpement.fr/securite/en-tetes-http-securite-wordpress/

## L’essentiel

- Les en-têtes de sécurité agissent au niveau du navigateur, en complément du code PHP
- send_headers permet de les ajouter sans toucher au serveur web
- Une CSP mal calibrée casse plus de sites qu'elle n'en protège

Un site WordPress parfaitement codé, avec des nonces partout, des sorties échappées et des routes REST bien protégées, reste vulnérable à certaines attaques que seul le navigateur peut bloquer. Le clickjacking, l'exécution de script injecté par une extension tierce compromise, ou le vol de cookie sur une connexion mal sécurisée ne se règlent pas uniquement dans le code PHP : ils se règlent aussi dans les en-têtes de réponse HTTP.

Ces en-têtes indiquent au navigateur comment se comporter face à la page reçue : autoriser ou non son affichage dans une iframe, n'exécuter que les scripts d'origines déclarées, forcer HTTPS pour toutes les requêtes futures. Ils forment une deuxième ligne de défense, indépendante du code de l'application, et souvent négligée sur les projets WordPress.

## Content-Security-Policy : la plus puissante, la plus délicate

La **Content-Security-Policy**, ou CSP, définit la liste des sources autorisées à fournir des scripts, des styles, des images ou des polices pour la page. Bien configurée, elle empêche l'exécution d'un script injecté par une faille XSS, même si la faille existe dans le code. Mal configurée, elle casse silencieusement des fonctionnalités entières : un plugin de statistiques qui charge un script externe, une police Google Fonts, une iframe de vidéo intégrée peuvent tous se retrouver bloqués.

```
add_action( 'send_headers', function () {
    header(
        "Content-Security-Policy: default-src 'self'; " .
        "script-src 'self' https://www.googletagmanager.com; " .
        "style-src 'self' 'unsafe-inline'; " .
        "img-src 'self' data: https:;"
    );
} );
```

La meilleure méthode pour introduire une CSP consiste à démarrer en mode `Content-Security-Policy-Report-Only`, qui journalise les violations sans bloquer réellement le contenu, puis à ajuster la politique pendant plusieurs semaines avant de passer en mode bloquant.

## HSTS : forcer HTTPS durablement

L'en-tête **Strict-Transport-Security** indique au navigateur de ne plus jamais tenter de charger le site en HTTP, même si un lien ou un favori pointe vers cette version, pendant une durée définie en secondes.

> L'essentiel à retenir : Les en-têtes de sécurité agissent au niveau du navigateur, en complément du code PHP ; send_headers permet de les ajouter sans toucher au serveur web ; Une CSP mal calibrée casse plus de sites qu'elle n'en protège

```
add_action( 'send_headers', function () {
    header( 'Strict-Transport-Security: max-age=31536000; includeSubDomains' );
} );
```

Cet en-tête ne doit être ajouté qu'une fois HTTPS totalement fiable sur le domaine et tous ses sous-domaines concernés : une erreur de certificat après activation de HSTS rend le site inaccessible pendant toute la durée du `max-age`, sans possibilité de repli en HTTP.

## X-Frame-Options et X-Content-Type-Options

`X-Frame-Options` empêche l'affichage du site dans une iframe sur un domaine tiers, ce qui referme la porte au clickjacking, une technique qui superpose des éléments invisibles pour piéger un clic. `X-Content-Type-Options: nosniff` empêche le navigateur de deviner le type d'un fichier au-delà de ce que déclare son en-tête `Content-Type`, ce qui referme certaines attaques par confusion de type MIME.

| En-tête | Rôle | Valeur type |
| --- | --- | --- |
| X-Frame-Options | Empêche l'affichage en iframe externe | SAMEORIGIN |
| X-Content-Type-Options | Empêche le sniffing de type MIME | nosniff |
| Referrer-Policy | Limite les informations transmises au clic sur un lien | strict-origin-when-cross-origin |

## Ajouter les en-têtes sans toucher au serveur

Sur un projet où l'on ne maîtrise pas la configuration Nginx ou Apache, le hook `send_headers` permet d'ajouter ces en-têtes directement depuis un plugin ou le fichier `functions.php`, ce qui rend la configuration versionnable avec le reste du code.

```
add_action( 'send_headers', function () {
    header( 'X-Frame-Options: SAMEORIGIN' );
    header( 'X-Content-Type-Options: nosniff' );
    header( 'Referrer-Policy: strict-origin-when-cross-origin' );
} );
```

Sur un projet où l'accès au serveur est possible, ajouter ces en-têtes directement dans la configuration Nginx ou dans le fichier `.htaccess` reste préférable : ils s'appliquent alors même aux ressources statiques servies en dehors du cycle de chargement de WordPress.

## Vérifier ce qui est réellement envoyé

Un en-tête ajouté dans le code n'est pas toujours celui qui arrive jusqu'au navigateur : un CDN, un reverse proxy ou un cache de page peuvent le réécrire ou le supprimer. Des outils comme *securityheaders.com* permettent de vérifier en quelques secondes les en-têtes réellement reçus par un client externe, et attribuent une note globale qui aide à prioriser les réglages manquants.

- Tester après chaque changement de configuration serveur ou de CDN
- Vérifier la page d'accueil, une page d'article et une page de panier ou de compte, car certains caches diffèrent selon le contexte
- Documenter la politique CSP choisie pour que l'équipe sache pourquoi telle source est autorisée

> Sur mes projets, j'ajoute toujours ces en-têtes en mode « report only » d'abord, je laisse tourner une à deux semaines, puis je bascule en mode strict. Ça évite le coup de fil du client un vendredi soir parce qu'une iframe de paiement ne charge plus.

## En résumé

Les en-têtes HTTP de sécurité ne remplacent aucune bonne pratique de code, mais ils referment des angles morts que le PHP seul ne peut pas couvrir : l'affichage en iframe, l'exécution de script sur une origine imprévue, le chargement accidentel en HTTP. Cinq en-têtes bien choisis, testés progressivement en mode non bloquant, suffisent à faire franchir un vrai palier de sécurité à un site WordPress sans toucher à une seule ligne de logique métier.
