En-têtes HTTP de sécurité : HSTS, CSP et ce qu'un scanner
vous cache
HSTS, CSP, X-Frame-Options : un scanner d'en-têtes note votre site avec une grille datée. Ce qu'il vous fait croire, ce qu'il rate, et le réglage réel de chaque en-tête HTTP, mesures curl à l'appui.
own2pwn9 min de lecture

Vos en-têtes sont-ils cohérents sur tout le périmètre ?
L'EASM vérifie chaque hôte exposé, pas seulement la page d'accueil.
Cartographier ma surface d'attaquePassez trois sites au crible d'un scanner d'en-têtes et vous obtenez trois lettres, de A à F, comme un contrôle d'hygiène. C'est rassurant, et c'est trompeur. En septembre 2026, une simple commande curl -sI sur quelques sites publics donne un aperçu plus honnête que n'importe quelle grille de notation. WordPress.org ne renvoie qu'un seul en-tête de sécurité. GitHub en envoie une pile complète, mais désactive volontairement un en-tête que la plupart des scanners réclament encore. Cloudflare, société de sécurité, expédie cet en-tête déprécié tel quel. Trois stratégies, et un scanner qui les range mal.
Les en-têtes HTTP de sécurité sont des instructions que votre serveur ajoute à chaque réponse pour dicter au navigateur comment se comporter : n'accepte que le HTTPS, refuse de m'afficher dans une iframe, n'exécute que les scripts que j'autorise. Bien réglés, ils ferment des classes entières d'attaques sans une ligne de code applicatif. Mal réglés, ou copiés d'un tutoriel de 2016, ils endorment sans protéger. On les passe un par un, avec le vrai réglage de chacun, le piège qui va avec, et ce qu'un scanner ne vous montre pas.
Un en-tête n'est qu'une consigne
HSTS : forcer le HTTPS, sans marche arrière
Strict-Transport-Security, ou HSTS, est le plus utile de la liste et le plus dangereux à mal poser. Il répond à un trou précis : même un site en HTTPS partout reste vulnérable sur la première requête, quand l'utilisateur tape exemple.fr sans préfixe et que le navigateur tente d'abord le HTTP clair. Un attaquant sur le même réseau intercepte cette requête et n'a plus qu'à rester en HTTP. HSTS ferme la fenêtre : une fois l'en-tête reçu, le navigateur mémorise la consigne et réécrit lui-même http:// en https:// avant d'émettre quoi que ce soit, pendant toute la durée du max-age.
La valeur recommandée par le projet OWASP Secure Headers est max-age=63072000; includeSubDomains, soit deux ans, étendu à tous les sous-domaines. Le max-age est une durée en secondes, remise à zéro à chaque visite : tant que l'utilisateur revient, la protection ne s'éteint jamais. Pour un hsts test rapide, pas besoin d'un service en ligne, la ligne brute suffit :
$ curl -sI https://github.com | grep -i strict-transport
strict-transport-security: max-age=31536000; includeSubdomains; preload
$ curl -sI https://www.wordpress.org | grep -i strict-transport
# (rien) : pas d'en-tete HSTS du toutLe troisième mot de la ligne GitHub, preload, est celui qui mérite un panneau d'avertissement. Il signale votre intention de figurer sur la liste de préchargement HSTS, une liste compilée par les navigateurs eux-mêmes. Un domaine préchargé est forcé en HTTPS avant même la première visite, sans avoir jamais servi le moindre en-tête au client. Les conditions d'entrée sont un max-age d'au moins un an, includeSubDomains, la directive preload, et une redirection HTTP vers HTTPS.
Le preload ne se retire pas d'un revers de main
X-XSS-Protection : l'en-tête que les scanners réclament encore à tort
Voici le cas d'école du décalage entre les scanners et l'état de l'art. X-XSS-Protection activait un filtre anti-XSS intégré aux anciens navigateurs. Il a été retiré de Chrome et d'Edge, jamais implémenté par Firefox, et sa page MDN porte un double bandeau "Deprecated" et "Non-standard", avec un avertissement net : dans certains cas, cet en-tête peut créer des vulnérabilités XSS sur un site qui en était exempt. Le filtre lui-même était devenu un vecteur.
Le projet OWASP Secure Headers ne se contente pas de le déconseiller : il recommande de l'envoyer avec la valeur 0, pour désactiver explicitement le filtre plutôt que de laisser le navigateur choisir son comportement par défaut. La bonne pratique est donc l'inverse de ce qu'affiche encore beaucoup d'outillage : non pas 1; mode=block, mais 0, ou rien du tout. Regardez ce que font deux acteurs que personne n'accusera de négliger la sécurité :
$ curl -sI https://github.com | grep -i x-xss
x-xss-protection: 0 # desactive : la bonne pratique actuelle
$ curl -sI https://www.cloudflare.com | grep -i x-xss
x-xss-protection: 1; mode=block # l'ancienne valeur, toujours servieGitHub désactive. Cloudflare, dont c'est pourtant le métier, envoie encore la vieille valeur. Un scanner d'en-têtes qui pénalise l'absence de X-XSS-Protection vous pousse donc vers le mauvais réglage, au nom d'une case à cocher. C'est le premier "ce qu'un scanner vous fait croire" : une note qui récompense un en-tête que les navigateurs ont eux-mêmes enterré. La vraie protection contre le XSS réfléchi, elle, s'écrit ailleurs.
Content Security Policy : le vrai rempart, et le piège du report-only
La Content-Security-Policy est l'en-tête qui remplace le filtre XSS déprécié, et de très loin le plus puissant de la liste. Elle déclare au navigateur quelles sources de scripts, de styles, d'images ou de trames sont autorisées. Une politique script-src 'self' interdit tout script inline ou distant non prévu : un XSS injecté dans la page ne s'exécute plus, même si l'attaquant a réussi à écrire son <script> dans le HTML. C'est une défense en profondeur qui transforme une faille exploitable en tentative avortée.
Le piège tient en un suffixe. Il existe deux en-têtes jumeaux : Content-Security-Policy, qui applique et bloque, et Content-Security-Policy-Report-Only, qui applique la même politique mais se contente de signaler les violations sans rien empêcher. Le second est fait pour roder une CSP en production sans casser le site. Le drame classique, c'est de l'y laisser : la politique semble en place, les rapports arrivent, et rien n'est bloqué. Un scanner voit un en-tête CSP présent et donne le point. Le navigateur, lui, n'a jamais rien interdit.
L'autre écueil est la CSP de façade : une politique qui contient 'unsafe-inline' sur script-src autorise précisément les scripts inline qu'un XSS injecte, donc ne protège de presque rien tout en affichant un en-tête rassurant. Sur les CMS, le sujet est épineux : WordPress et ses extensions posent du JavaScript inline partout, et une CSP stricte casse le thème. On détaille ce compromis, et comment le tenir, dans notre guide pour sécuriser un site WordPress. La CSP mérite qu'on la construise, pas qu'on la copie.
La sortie propre du problème existe depuis longtemps : le nonce et le hash. Plutôt qu''unsafe-inline', on déclare script-src 'nonce-XyZ...' et on répète ce jeton aléatoire, régénéré à chaque réponse, sur chaque balise <script> légitime. Le navigateur n'exécute que les scripts porteurs du bon nonce ; un script injecté par un XSS ne le connaît pas, donc ne tourne pas. C'est plus de travail côté application, et c'est précisément ce travail qui sépare une CSP qui protège d'une CSP qui décore. La version 'sha256-...' autorise un bloc inline par son empreinte, utile pour un script figé qu'on ne veut pas déplacer.
frame-ancestors remplace X-Frame-Options
frame-ancestors 'none' fait le même travail anti-clickjacking que X-Frame-Options: DENY, en mieux : elle gère plusieurs origines autorisées et prime sur l'ancien en-tête dans les navigateurs modernes. On garde souvent les deux par prudence envers les clients anciens, mais le signal qui compte désormais, c'est frame-ancestors.X-Frame-Options, nosniff, Referrer-Policy, Permissions-Policy
Restent quatre en-têtes plus discrets, chacun fermant une porte précise. Aucun ne remplace la CSP, mais ils coûtent une ligne de configuration et couvrent des angles qu'elle ne traite pas. X-Frame-Options: DENY interdit qu'on affiche votre site dans une iframe, ce qui coupe le clickjacking (superposer votre page sous un leurre pour détourner les clics). X-Content-Type-Options: nosniff interdit au navigateur de deviner le type d'un fichier au lieu de croire l'en-tête Content-Type : sans lui, un fichier uploadé et servi en text/plain peut se faire réinterpréter en HTML exécutable.
Referrer-Policy contrôle ce que votre site divulgue dans l'en-tête Referer quand un utilisateur suit un lien sortant. Sans réglage, l'URL complète part vers le site tiers, y compris d'éventuels jetons ou identifiants glissés dans le chemin. La valeur strict-origin-when-cross-origin envoie l'origine seule vers l'extérieur. Enfin, Permissions-Policy désactive les API sensibles du navigateur (caméra, micro, géolocalisation, USB) que votre site n'utilise pas, réduisant d'autant ce qu'un script injecté pourrait solliciter. Le tableau ci-dessous condense les valeurs et les pièges.
| En-tête | Rôle | Valeur recommandée | Le piège |
|---|---|---|---|
| Strict-Transport-Security | Force le HTTPS | max-age=63072000; includeSubDomains | Le preload ne se retire pas vite |
| Content-Security-Policy | Cadre les scripts et ressources | script-src 'self'; object-src 'none' | Report-only ne bloque rien ; unsafe-inline annule tout |
| X-Frame-Options | Anti-clickjacking | DENY | Supplanté par frame-ancestors |
| X-Content-Type-Options | Bloque le MIME sniffing | nosniff | Aucune valeur alternative, c'est tout ou rien |
| Referrer-Policy | Limite la fuite d'URL | strict-origin-when-cross-origin | Le défaut varie selon le navigateur |
| Permissions-Policy | Coupe les API inutilisées | camera=(), microphone=(), geolocation=() | Syntaxe distincte de l'ancien Feature-Policy |
| X-XSS-Protection | Ancien filtre XSS (déprécié) | 0 (ou absent) | Les scanners réclament encore 1; mode=block |
Ce qu'un scanner d'en-têtes ne voit pas
Un scanner d'en-têtes lit une URL, une seule, presque toujours la racine du domaine. C'est sa limite structurelle. Il ne sait pas qu'à côté de votre site vitrine parfaitement noté vivent un espace client sur un sous-domaine, une API sur un autre, un vieux back-office oublié qui, lui, ne renvoie aucun de ces en-têtes. Le durcissement HTTP est une propriété de chaque hôte exposé, pas du domaine principal. Une note A sur la page d'accueil ne dit rien des trente autres services que vous exposez sans le savoir.
C'est exactement le champ de la gestion de la surface d'attaque externe (EASM). Avant de vérifier des en-têtes, il faut savoir sur quoi les vérifier, et l'inventaire est presque toujours incomplet : la découverte des actifs exposés remonte régulièrement des hôtes que l'équipe avait perdus de vue. Une fois la cartographie faite, le contrôle des en-têtes de sécurité devient une case parmi des centaines dans une gestion des vulnérabilités continue, plutôt qu'un audit ponctuel d'une seule page.
C'est aussi la différence entre un scanner d'en-têtes gratuit et un scanner de vulnérabilité appliqué à tout un périmètre. Le premier vous donne une note sur une page ; le second, s'il est piloté par un inventaire à jour, vous dit quels hôtes, parmi tous ceux que vous exposez, laissent la porte ouverte. La surveillance de surface d'attaque d'own2pwn repère les en-têtes manquants ou incohérents sur l'ensemble des services découverts, pas seulement sur celui que vous auriez pensé à tester.
À retenir
- HSTS ferme la fenêtre de la première requête HTTP. Valeur solide :
max-age=63072000; includeSubDomains. Lepreloadest quasi irréversible, on ne le pose que sur un arbre 100 % HTTPS. - X-XSS-Protection est déprécié. MDN et OWASP recommandent la valeur
0, pas1; mode=block. Un scanner qui exige le contraire suit une grille périmée. - La CSP est le vrai rempart anti-XSS. Attention au report-only oublié en production et à l'
unsafe-inlinequi vide la politique de son sens. - frame-ancestors, nosniff, Referrer-Policy, Permissions-Policy coûtent une ligne chacun et couvrent clickjacking, MIME sniffing, fuite de referer et API inutiles.
- Un bon score de scanner ne concerne qu'une page. Le durcissement est une propriété de chaque hôte : sans inventaire complet, la note ment par omission.
Poser sept en-têtes sur sa page d'accueil prend dix minutes. Savoir que les mêmes sept en-têtes sont posés, et bien posés, sur chacun des services qu'on expose sur Internet, c'est un travail d'inventaire continu. Si vous ne savez pas combien d'hôtes portent votre nom de domaine, commencez par les cartographier avant de les noter. Et si vous voulez qu'un humain regarde ce que les en-têtes laissent passer sur une application précise, parlez-nous de votre périmètre.
Questions fréquentes sur les en-têtes HTTP de sécurité
Qu'est-ce que l'en-tête HSTS et à quoi sert-il ?
HSTS (Strict-Transport-Security) est un en-tête de réponse HTTP qui ordonne au navigateur de ne plus jamais contacter le domaine en HTTP clair pendant une durée donnée (max-age). Il bloque les attaques de rétrogradation de protocole et le vol de cookies sur une première connexion interceptée. Le navigateur mémorise la consigne et réécrit lui-même http:// en https:// avant même d'émettre la requête.
Comment tester HSTS sur un site (hsts test) ?
La commande curl -sI https://votre-domaine renvoie tous les en-têtes de réponse. Cherchez la ligne strict-transport-security : elle doit indiquer un max-age d'au moins un an, idéalement includeSubDomains. C'est plus fiable qu'un scanner en ligne, car vous voyez la valeur brute sans interprétation. Un check HSTS complet vérifie aussi que le HTTP redirige bien vers HTTPS.
Faut-il encore envoyer l'en-tête X-XSS-Protection ?
Non. X-XSS-Protection est déprécié. MDN le classe non standard et prévient que sa valeur 1; mode=block peut elle-même introduire des vulnérabilités. Le projet OWASP Secure Headers recommande explicitement la valeur 0, pour désactiver le filtre XSS des navigateurs, et de s'appuyer sur une Content Security Policy à la place. Les scanners qui réclament encore cet en-tête suivent une grille datée.
Qu'est-ce que la Content Security Policy en report-only ?
Content-Security-Policy-Report-Only applique la même politique que Content-Security-Policy mais sans rien bloquer : le navigateur signale les violations sans les empêcher. C'est un mode de rodage, utile pour ajuster une CSP sans casser le site. Le piège est de l'oublier en production : une CSP en report-only ne protège de rien, elle observe. Un scanner naïf voit un en-tête CSP présent et donne une bonne note.
Le préchargement HSTS (preload) est-il réversible ?
Très difficilement. Une fois votre domaine ajouté à la liste de préchargement HSTS, le retrait est lent : la documentation officielle prévient qu'une suppression met des mois à atteindre les utilisateurs via une mise à jour du navigateur, sans garantie sur les autres. Si un sous-domaine ne peut plus servir de HTTPS, il devient injoignable. On ne soumet un domaine au preload qu'en connaissance de cause.
Un bon score sur un scanner d'en-têtes signifie-t-il que le site est sûr ?
Non. Un scanner d'en-têtes ne lit qu'une page, souvent la racine, et note la présence d'en-têtes, pas leur cohérence avec le reste de l'application. Un site peut afficher une note A avec une CSP truffée d'unsafe-inline, ou n'avoir durci que sa page d'accueil. La grille de notation est utile pour dégrossir, jamais suffisante pour conclure qu'un périmètre est protégé.
Veille sécurité
La suite, une fois par mois
Ce qui bouge vraiment sur la surface d'attaque externe, NIS2 et la sécurité applicative, écrit par le pentester qui signe ces articles. Un envoi par mois, désinscription en un clic.
Votre adresse ne sert qu'à cet envoi. Voir la politique de confidentialité.
Articles liés
appsec
EASM : qu'est-ce que la gestion de surface d'attaque externe ?
L'EASM en clair : définition, fonctionnement, et ce qui le distingue d'un scanner ou d'un pentest. Comment cartographier votre surface d'attaque externe et qui en a besoin.
appsec
Scan de ports : lire le résultat, pas réciter la commande
Un scan de ports n'est utile que si vous savez lire ce qu'il rend. open, filtered, closed, versions, scripts NSE : on décortique une sortie nmap réelle sur une cible autorisée, puis ce qu'un module EASM en fait à votre place, en continu.
appsec
Censys, Onyphe, Shodan : lire l'internet sans le scanner
Censys, Onyphe et Shodan indexent ce que l'internet public expose : ce que chaque moteur voit, ses écarts de couverture, son délai de rafraîchissement et les requêtes exactes pour auditer sa surface.