Headers sécurité HTTP : CSP, HSTS, X-Frame-Options, que mettre ?
CSP, HSTS, X-Frame-Options, Referrer-Policy : quels headers sécurité HTTP activer, dans quel ordre, et comment les tester sans casser votre site.
Headers sécurité HTTP : à quoi servent ces en-têtes de réponse ?
À chaque ouverture de page, votre serveur renvoie le contenu demandé. Mais il ne s'arrête pas là : il ajoute aussi une série d'informations techniques que personne ne voit, les en-têtes HTTP. Type de fichier, durée de mise en cache… chacun a son rôle. Une famille précise, les headers sécurité HTTP, sert à donner au navigateur des consignes de protection.
Le principe tient en une phrase : le serveur dit au navigateur ce qu'il a le droit de faire. Charger tel script ? Afficher la page dans un cadre ? Basculer en HTTP non chiffré ? Le navigateur applique ces règles à la lettre. Comprenez bien une chose : vous ne corrigez pas une faille dans votre code, vous dressez une barrière de plus devant elle.
Pourquoi un dirigeant de PME devrait s'en préoccuper
Votre site rapporte de l'argent ? Alors il collecte des contacts, des paiements, parfois des données clients. Une seule injection de script malveillant sur le formulaire de devis suffit à exposer vos prospects. Les security headers ne règlent pas tout. Ils limitent en revanche nettement les dégâts d'une faille XSS ou d'un détournement de clic.
Reste la question de l'image. N'importe qui peut noter les en-têtes de votre site en quelques secondes avec un outil d'audit gratuit : un concurrent, un client grand compte, le prestataire informatique d'un partenaire. Pour une entreprise qui vend du sérieux, une note faible envoie un mauvais signal.
Ce que ces en-têtes ne font pas
Soyons clairs : aucun header ne remplace les mises à jour, un mot de passe solide ou une sauvegarde. Un back-office mal verrouillé, une extension vulnérable ? Il ne les protège pas. C'est une couche de défense parmi d'autres, à intégrer dans une démarche globale (celle de notre checklist sécurité site web, par exemple).
Les security headers à mettre en place, un par un
Voici la liste que je recommande à la plupart des sites vitrines et e-commerce. Pour chaque en-tête, vous trouverez ce qu'il bloque, la valeur de départ conseillée et le piège à connaître. On avance du plus simple au plus délicat.
Strict-Transport-Security (HSTS) : forcer le chiffrement
Strict-Transport-Security oblige le navigateur à toujours passer en HTTPS sur votre domaine, même quand quelqu'un tape l'adresse en http. Il désamorce une attaque classique de type man-in-the-middle, où un réseau Wi-Fi piégé intercepte la première requête, celle qui part en clair. Sans lui, votre certificat SSL peut être contourné lors de cette toute première connexion.
La valeur combine une durée et des options. max-age fixe, en secondes, combien de temps le navigateur retient la consigne. includeSubDomains étend la règle à tous vos sous-domaines. Quant à preload, il permet de demander l'inscription du domaine dans une liste intégrée aux navigateurs.
- Pour démarrer prudemment : « Strict-Transport-Security: max-age=300 », soit cinq minutes, le temps de vérifier que rien ne casse.
- En vitesse de croisière : « max-age=31536000; includeSubDomains », soit un an.
- Preload : uniquement si vous êtes certain que tous vos sous-domaines, présents et futurs, fonctionneront en HTTPS.
Content-Security-Policy (CSP) : contrôler les sources de contenu
De toute la liste, la content-security-policy est l'en-tête le plus puissant. Elle établit une liste blanche des sources autorisées pour chaque type de ressource : scripts, feuilles de style, images, polices, vidéos, connexions. Le navigateur bloque tout le reste. Un script injecté depuis un domaine inconnu ? Il ne s'exécute tout simplement pas.
Elle s'écrit avec des directives. Chacune cible un type de ressource et liste les origines permises. Les plus courantes :
- default-src : la règle par défaut, appliquée à tout type de contenu non précisé ailleurs.
- script-src : les sources autorisées pour le JavaScript, et la directive la plus sensible.
- style-src : les origines des feuilles de style CSS.
- img-src : les images, y compris celles en data: si vous en utilisez.
- connect-src : les appels réseau lancés par vos scripts, vers une API ou un outil de mesure par exemple.
- frame-ancestors : qui a le droit d'afficher votre page dans une iframe.
- upgrade-insecure-requests : transforme automatiquement les appels http en https.
'self' désigne votre propre origin, autrement dit votre domaine ; 'none' interdit tout. Et un joker « all » ? Il n'existe pas en CSP : c'est l'astérisque qui joue ce rôle, et c'est précisément ce qu'il faut éviter sur script-src. Une politique stricte refuse aussi 'unsafe-inline', qui autorise le code écrit directement dans la page. C'est la porte d'entrée favorite des injections.
Les sites plus exigeants disposent de directives avancées. Avec require-trusted-types-for 'script', le code JavaScript doit passer par des fonctions contrôlées avant de modifier la page, ce qui intéresse surtout les applications web riches, beaucoup moins un site vitrine. Le déploiement de la CSP mérite une section à part, plus bas : c'est là que se jouent la plupart des échecs.
X-Frame-Options : empêcher l'affichage dans un frame
X-Frame-Options protège contre le clickjacking. Le scénario ? Un site malveillant charge votre page dans un cadre invisible, puis pousse l'internaute à cliquer sur un bouton qu'il ne voit pas (valider une commande, changer un réglage). Interdisez l'affichage dans un frame, et la manœuvre tombe à plat.
Deux valeurs servent vraiment. DENY interdit tout affichage en iframe ; SAMEORIGIN ne l'autorise que depuis votre propre domaine. La CSP propose aujourd'hui un équivalent plus souple, frame-ancestors, qui liste précisément les sites autorisés. Mon conseil : gardez les deux, X-Frame-Options pour les anciens navigateurs, frame-ancestors pour le contrôle fin.
X-Content-Type-Options : bloquer les faux types de fichiers
Pendant longtemps, les navigateurs ont tenté de deviner le type d'un fichier en lisant son contenu, quitte à ignorer ce que le serveur annonçait. Résultat : un fichier présenté comme une image pouvait finir exécuté comme du script. Avec la valeur nosniff, l'en-tête content-type-options interdit cette devinette.
Le navigateur s'en tient alors strictement au Content-Type envoyé par le serveur. Une seule valeur possible, presque aucun effet de bord : c'est l'en-tête le plus simple de la liste. Une précaution tout de même. Vérifiez que votre serveur déclare correctement le content-type de vos fichiers CSS et JavaScript, sinon ils seront refusés.
Referrer-Policy : maîtriser les informations transmises
Un visiteur clique sur un lien sortant. Son navigateur indique alors au site de destination la page d'où il vient : c'est le referrer. Vos adresses contiennent des paramètres sensibles, un numéro de dossier ou un jeton de réinitialisation ? Ces informations partent chez des tiers.
Je recommande strict-origin-when-cross-origin, qui offre un bon équilibre. En navigation interne, l'adresse complète est transmise ; vers les sites extérieurs, seulement le nom de domaine ; et rien du tout si l'on passe de HTTPS à HTTP. Vos outils de mesure d'audience continuent de fonctionner. Plus radicale, la referrer-policy no-referrer coupe toute transmission, au prix d'une partie de vos données de provenance.
Permissions-Policy : désactiver certaines fonctionnalités du navigateur
Caméra, micro, géolocalisation, paiement intégré : les navigateurs donnent accès à bien des capacités. La permissions-policy sert à désactiver celles que votre site n'utilise pas. Si un script tiers compromis tente d'allumer la caméra, le navigateur refuse.
Côté syntaxe, chaque capacité est suivie des origines autorisées entre parenthèses, et des parenthèses vides valent interdiction totale. Par exemple : « Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=(self) ». Adaptez la liste à vos besoins réels. Un site de prise de rendez-vous avec carte interactive gardera peut-être la géolocalisation pour son propre domaine.
Les en-têtes à oublier
Des conseils datés circulent encore. X-XSS-Protection, abandonné par les navigateurs modernes, peut même créer des failles : désactivez-le ou ne l'envoyez pas. Feature-Policy ? Remplacé par Permissions-Policy. Pensez enfin à retirer les en-têtes qui trahissent votre version de serveur ou de langage, comme X-Powered-By. Pourquoi offrir des indices gratuits à un attaquant ?
Déployer une content-security-policy sans casser son site : la méthode pas à pas
Une CSP mal réglée peut bloquer votre outil de prise de rendez-vous, votre chat, vos pixels publicitaires ou vos polices. Le pire ? Le site a l'air de fonctionner pendant que les conversions s'effondrent en silence. D'où une règle d'or : observer avant de bloquer.
Étape 1 : inventorier les ressources chargées
Ouvrez les outils de développement du navigateur, onglet Réseau, puis parcourez les pages clés : accueil, fiche produit, panier, formulaire de contact, page de confirmation. Notez chaque domaine externe qui fournit des ressources. Vous tomberez souvent sur des polices, une carte, une vidéo, un outil de mesure, des balises publicitaires et un widget d'avis.
Vous passez par Google Tag Manager ? Redoublez d'attention. Chaque balise ajoutée au conteneur peut charger un nouveau domaine, et si la CSP ne suit pas, les nouvelles balises seront bloquées sans que personne ne s'en aperçoive.
Étape 2 : publier la politique en mode rapport
Avec l'en-tête Content-Security-Policy-Report-Only, la politique tourne en mode observation. Rien n'est bloqué : le navigateur signale simplement, dans la console ou à une adresse de collecte, ce qu'il aurait bloqué. Écrivez votre première version, publiez-la dans cet en-tête, et laissez tourner.
Pour un site vitrine, partez d'une base raisonnable : default-src 'self' ; img-src 'self' data: ; ajoutez ensuite vos domaines tiers dans script-src, style-src et connect-src, puis terminez par frame-ancestors 'self' et upgrade-insecure-requests. Gardez une trace écrite de chaque domaine ajouté et de la raison de sa présence (vous vous en féliciterez plus tard).
Étape 3 : analyser les violations et ajuster
Les rapports arrivent vite. Une partie signale des oublis légitimes : un sous-domaine de l'outil de paiement, une police servie par un autre serveur. Le reste vient souvent d'extensions installées dans le navigateur de vos visiteurs, qu'il faut ignorer. Ajoutez les sources légitimes une par une, puis relancez l'observation.
Combien de temps faut-il ? Tout dépend du nombre d'outils tiers et du trafic. Un site très simple se stabilise rapidement. Un e-commerce aux campagnes nombreuses et aux tunnels de paiement multiples demande plusieurs cycles, parce que certaines pages ne sont visitées que rarement.
Étape 4 : traiter les scripts en ligne
Voilà le point dur. Beaucoup de CMS et d'extensions écrivent leur JavaScript directement dans le HTML. Pour éviter 'unsafe-inline', deux options : déplacer ce code dans des fichiers séparés, ou recourir à un nonce. Le nonce est une valeur aléatoire générée à chaque affichage de page, ajoutée à la fois dans l'en-tête et dans la balise script autorisée.
Ce travail revient au développeur, puisqu'il touche au code du site ou du thème. Sur un site sur-mesure, on le prévoit généralement sans peine dès la conception. Sur un CMS chargé d'extensions, il peut au contraire s'éterniser, voire devenir impossible sans compromis. Dans ce cas, je préfère une CSP partielle et maîtrisée à pas de CSP du tout.
Étape 5 : passer en mode bloquant et surveiller
Les rapports ne remontent plus que du bruit ? Basculez la même politique dans l'en-tête Content-Security-Policy. Testez tout de suite vos parcours de conversion : formulaire, paiement, prise de rendez-vous. Laissez la collecte de rapports active, car chaque nouvel outil marketing exigera l'ajout d'une source.
Où ajouter ces headers : Apache, nginx, CMS ou CDN
On peut poser un header de sécurité à plusieurs niveaux. Lequel choisir ? Cela dépend de votre hébergement et de qui a la main sur la configuration. Tenez-vous-en à un seul niveau, pour éviter les doublons contradictoires.
Sur un serveur Apache
Sur Apache, module headers activé, les règles vont dans la configuration du site ou dans le fichier .htaccess. Chaque ligne commence par header always set, suivi du nom de l'en-tête puis de sa valeur. Ne retirez pas le mot always : grâce à lui, l'en-tête part aussi sur les pages d'erreur et les redirections, pas seulement sur les réponses réussies. Voici ce qui suit ce préfixe pour les en-têtes simples :
- Strict-Transport-Security max-age=31536000;includeSubDomains
- X-Frame-Options SAMEORIGIN
- X-Content-Type-Options nosniff
- Referrer-Policy strict-origin-when-cross-origin
Une CSP ou une Permissions-Policy contient des espaces : entourez sa valeur de guillemets dans le fichier de configuration. Après chaque modification, rechargez la configuration et vérifiez qu'aucune erreur de syntaxe ne fait tomber le site.
Sur nginx
Côté nginx, c'est la directive add_header qui joue ce rôle, avec le paramètre always pour couvrir toutes les réponses. Une subtilité piège beaucoup de monde : dès qu'un bloc de configuration déclare ses propres add_header, il n'hérite plus de ceux du niveau supérieur. Une seule règle ajoutée pour un dossier, et tous vos en-têtes de sécurité disparaissent sur ce dossier !
Sur WordPress et les autres CMS
Certaines extensions ajoutent les en-têtes depuis l'interface d'administration. Pour dépanner, ça marche. Mais c'est une dépendance de plus, qui s'exécute tard, au niveau de PHP. Si vous le pouvez, passez plutôt par la configuration serveur, plus fiable. Pour le reste du durcissement, notre guide pour sécuriser WordPress complète ce travail.
Sur un CDN ou un hébergement géré
Votre site passe par un CDN ou une plateforme gérée ? Leur tableau de bord permet souvent de définir des règles de transformation des réponses, bien pratique quand on n'a pas accès au serveur. Sur une plateforme e-commerce hébergée, en revanche, vous ne contrôlez parfois qu'une partie des en-têtes. Renseignez-vous avant de promettre une note parfaite.
Tester le résultat
Trois vérifications suffisent. D'abord le navigateur : l'onglet Réseau des outils de développement affiche les en-têtes de réponse de chaque page. Ensuite la ligne de commande, où une requête de type curl -I renvoie la tête de la réponse. Enfin les scanners publics, qui attribuent une note et listent les en-têtes manquants ; Mozilla Observatory et securityheaders.com sont les plus connus.
Ce qui fait varier l'effort, et les pièges à éviter
Sur un serveur que l'on maîtrise, activer HSTS, X-Frame-Options, nosniff, Referrer-Policy et Permissions-Policy prend peu de temps. La CSP, c'est une autre histoire : d'une demi-journée de réglage à un vrai chantier. Plutôt qu'un chiffre, voici ce qui fait varier la charge.
Les facteurs qui pèsent sur le temps et le budget
- Le nombre d'outils tiers : chaque pixel, chat, carte ou widget d'avis ajoute des sources à autoriser et à tester.
- La quantité de code en ligne : un thème qui écrit son JavaScript dans la page impose du travail de développement.
- L'accès à la configuration : un serveur dédié se règle librement, alors qu'une plateforme fermée limite les options.
- Le nombre de sous-domaines, à vérifier un par un avant d'étendre HSTS.
- Les intégrations en iframe : configurateurs, simulateurs ou widgets intégrés chez des partenaires demandent des règles par page.
- La fréquence des changements marketing : plus vous ajoutez de balises, plus la maintenance de la CSP compte.
Chez RankerSquare, un site vitrine sur-mesure est proposé dès 19,90 € par mois en abonnement, et nous pensons ces en-têtes dès la conception, pas en rattrapage. Audit ou mise en conformité d'un site existant ? Tout dépend des facteurs ci-dessus, donc c'est sur devis. Pour un nouveau projet, notre offre de création de site internet intègre cette configuration.
Les erreurs les plus fréquentes
- Copier une CSP trouvée en ligne : elle n'autorise pas vos outils et casse vos conversions.
- Semer des astérisques ou 'unsafe-inline' partout pour faire taire les erreurs : la politique ne protège alors plus rien.
- Passer HSTS à un an avec preload dès le premier jour, sans inventaire des sous-domaines.
- Déclarer les mêmes en-têtes à deux niveaux, serveur et extension, avec des valeurs différentes.
- Oublier les pages d'erreur et les redirections, faute d'utiliser always.
- Ne jamais retester après l'arrivée d'une nouvelle balise publicitaire ou d'un nouveau module.
Ressources pour aller plus loin
Côté référence technique, rien ne vaut la documentation MDN de Mozilla : chaque en-tête, chaque directive, avec la compatibilité des navigateurs. Le projet OWASP Secure Headers tient à jour la liste des en-têtes recommandés et de ceux à abandonner. Et pour replacer ces protections dans le panorama des risques web, lisez notre article sur l'OWASP Top 10.
Questions fréquentes
Une ligne d'information que votre serveur ajoute à chaque réponse pour dire au navigateur comment se protéger. Elle peut imposer le HTTPS, limiter les sources de scripts ou interdire l'affichage en iframe. Le visiteur ne voit rien ; son navigateur, lui, applique ces règles automatiquement.
Tous deux empêchent un autre site d'afficher votre page dans un cadre. X-Frame-Options ne propose que deux choix utiles : interdire partout, ou autoriser votre seul domaine. La directive frame-ancestors de la CSP, elle, liste précisément les sites autorisés. Gardez les deux pour couvrir tous les navigateurs.
Google ne les annonce pas comme critères de classement, à l'exception du HTTPS, que HSTS vient renforcer. Leur intérêt pour le SEO reste indirect : un site piraté perd la confiance des visiteurs et peut être signalé comme dangereux. Ils protègent donc votre trafic plus qu'ils ne le font grimper.