Les en-têtes de sécurité HTTP sont des instructions que le serveur envoie avec chaque réponse pour que le navigateur applique des protections supplémentaires : forcer HTTPS (Strict-Transport-Security), limiter d’où peuvent être chargés les scripts et autres ressources (Content-Security-Policy), empêcher que le site soit intégré dans d’autres pages (X-Frame-Options / frame-ancestors), éviter que le navigateur « devine » les types de fichiers (X-Content-Type-Options), contrôler quelle information de provenance est envoyée à d’autres sites (Referrer-Policy) et désactiver les API du navigateur que vous n’utilisez pas (Permissions-Policy). Ils se configurent sur le serveur ou chez l’hébergeur, pas dans le HTML, et un site statique peut tous les avoir en quelques minutes.
Cet article explique ce que fait chacun, quelle valeur utiliser sur un site typique et comment vérifier qu’ils sont actifs.
Pourquoi ils comptent sur un site « sans rien à voler »
Un blog sans utilisateurs inscrits semble une cible peu intéressante, mais les en-têtes protègent vos visiteurs : ils évitent qu’un script tiers compromis injecte du code, que quelqu’un intègre votre site dans un cadre pour tromper des clics (clickjacking) ou qu’une connexion dégradée en HTTP permette de manipuler le contenu. Ils sont en outre gratuits en performance et signalent un site entretenu avec soin.
Les six en-têtes et leurs valeurs recommandées
1. Strict-Transport-Security (HSTS)
Indique au navigateur que, pendant la durée indiquée, il ne doit se connecter à votre domaine qu’en HTTPS, même si l’utilisateur tape http:// ou suit un ancien lien.
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
max-age=31536000: un an, en secondes.includeSubDomains: s’applique aussi aux sous-domaines. Assurez-vous que tous servent du HTTPS avant de l’activer.preload: permet d’inclure le domaine dans la liste de préchargement intégrée aux navigateurs, pour que même la première visite n’utilise pas HTTP. N’ajoutezpreloadque si vous allez vraiment soumettre le domaine à la liste ; c’est difficile à annuler.
Commencez avec un max-age court (par exemple 300) pour vérifier que rien ne casse, et augmentez-le ensuite.
2. Content-Security-Policy (CSP)
Le plus puissant et le plus délicat : il définit depuis quelles origines le navigateur peut charger scripts, styles, images, polices, connexions et iframes. Un script injecté depuis une origine non autorisée ne s’exécute tout simplement pas.
Un point de départ pour un site statique sans tiers :
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-src 'none'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'; upgrade-insecure-requests
Notes pratiques :
'self'est votre propre origine. Chaque service externe (analyse, publicité, polices, vidéos) doit être ajouté explicitement à la directive correspondante.- Évitez
'unsafe-inline'dansscript-src: il annule une grande partie de la protection. Si vous avez besoin de scripts inline, utilisez des nonces ou des hashes. Dansstyle-src, il est plus souvent toléré parce que beaucoup de colorateurs de code et de composants génèrent des styles inline, même si l’idéal est de le supprimer aussi. frame-ancestors 'none'remplaceX-Frame-Optionsdans les navigateurs modernes.- Testez d’abord avec
Content-Security-Policy-Report-Only, qui signale les violations sans rien bloquer, et regardez la console du navigateur.
3. X-Content-Type-Options
X-Content-Type-Options: nosniff
Empêche le navigateur d’interpréter un fichier comme un type différent de celui déclaré dans Content-Type (par exemple exécuter comme script quelque chose servi comme texte). Toujours, sans exception.
4. X-Frame-Options
X-Frame-Options: DENY
Interdit le chargement de votre page dans un <iframe> d’un autre site (protection contre le clickjacking). SAMEORIGIN autorise l’intégration seulement depuis votre propre domaine. Aujourd’hui, le frame-ancestors de la CSP couvre la même chose plus précisément ; gardez les deux pour les anciens navigateurs.
5. Referrer-Policy
Referrer-Policy: strict-origin-when-cross-origin
Contrôle quelle partie de l’URL d’origine est envoyée dans l’en-tête Referer en naviguant vers un autre site. Avec cette valeur, les autres domaines ne reçoivent que l’origine (https://blog.aimran.es) et jamais le chemin complet, et rien du tout en passant de HTTPS à HTTP. C’est la valeur par défaut des navigateurs modernes, mais la déclarer évite d’en dépendre.
6. Permissions-Policy
Permissions-Policy: camera=(), microphone=(), geolocation=(), interest-cohort=()
Désactive des API du navigateur que votre site n’utilise pas, y compris pour les iframes tiers que vous intégrez. La liste des fonctionnalités disponibles se trouve sur MDN ; déclarez vides (()) celles dont vous n’avez pas besoin.
Résumé en un tableau
| En-tête | Protège contre | Valeur recommandée |
|---|---|---|
Strict-Transport-Security |
Connexions HTTP, dégradation de protocole | max-age=31536000; includeSubDomains (+ preload si vous l’enregistrez) |
Content-Security-Policy |
Injection de scripts (XSS), ressources non autorisées | Commencer par default-src 'self' et ajouter les origines nécessaires |
X-Content-Type-Options |
Interprétation erronée des types de fichiers | nosniff |
X-Frame-Options |
Clickjacking (anciens navigateurs) | DENY |
Referrer-Policy |
Fuite d’URL internes vers des tiers | strict-origin-when-cross-origin |
Permissions-Policy |
Usage d’API sensibles par votre site ou des iframes | Désactiver celles que vous n’utilisez pas |
Où se configurent-ils
- Netlify et Cloudflare Pages : fichier
_headersdans le dossier publié. - Vercel : clé
headersdansvercel.json. - Nginx : directives
add_headerdans le blocserver. - Apache : directives
Header setdans la configuration ou dans.htaccess. - WordPress : via le serveur (préférable) ou un plugin de sécurité qui les ajoute.
Le mieux est de les garder dans un seul fichier versionné avec le code, pour qu’un changement du site (par exemple activer la publicité) implique de revoir la CSP dans le même commit.
Comment les vérifier
curl -sI https://blog.aimran.es/fr/ | grep -iE "strict-transport|content-security|x-content-type|x-frame|referrer-policy|permissions-policy"
Des outils en ligne comme securityheaders.com ou le HTTP Observatory de Mozilla analysent la réponse et notent la configuration. Et la console du navigateur affiche chaque violation de CSP avec la ressource bloquée, ce qui facilite l’ajustement de la politique.
Erreurs fréquentes
- Activer HSTS avec
preloadsans avoir tous les sous-domaines en HTTPS : ils cessent de fonctionner et le retour en arrière prend des mois. - Une CSP avec
'unsafe-inline'et'unsafe-eval'dans les scripts « pour que tout marche » : elle coche la case, mais protège peu. - Oublier la CSP en ajoutant un tiers (publicité, analyse, un widget) : la ressource est bloquée en silence et on a l’impression qu’elle « ne charge pas ».
- Configurer les en-têtes seulement sur la page d’accueil et pas sur le reste des routes ou sur les fichiers statiques.
- Ne pas tester en mode rapport avant de bloquer.
Conclusion
Six en-têtes, un fichier de configuration et quelques minutes : HSTS pour forcer HTTPS, CSP pour contrôler ce qui se charge, nosniff et X-Frame-Options/frame-ancestors pour fermer des vecteurs classiques, Referrer-Policy pour ne pas divulguer d’URL et Permissions-Policy pour éteindre ce que vous n’utilisez pas. Déployez d’abord la CSP en mode rapport, regardez la console, et versionnez les en-têtes avec le code pour qu’ils évoluent avec le site.