← Retour au blog
SécuritéScanaris Team · 6 min de lecture · October 04, 2026

Les en-têtes de sécurité HTTP expliqués pour les humains

Quand tu lances une app avec Cursor, Lovable ou v0, le serveur répond à chaque requête avec une série d'en-têtes HTTP : des instructions invisibles que le navigateur suit avant d'afficher quoi que ce soit. Une poignée d'entre eux décide d'une bonne partie de la sécurité de ton site, et presque aucun template ne les active. Ce guide explique ce que fait chacun, quelle valeur mettre, les erreurs qui cassent des choses et comment les configurer sur Vercel, Next.js, Nuxt, Netlify, Cloudflare ou nginx.

Ce qu'est un en-tête et comment voir les tiens

Un en-tête est une ligne de texte qui accompagne la réponse, de la forme Nom: valeur. Le navigateur la lit et change son comportement : charger ou non un script, forcer HTTPS, autoriser ou non ta page dans un iframe. Tu peux les voir dans les outils de développement (F12, onglet Network, clic sur le document principal, section Response Headers) ou depuis le terminal :

curl -I https://tondomaine.com

Si ceux ci-dessous n'apparaissent pas dans cette liste, ils ne sont pas configurés. Il n'y a pas de valeurs par défaut qui te sauvent.

Les sept qui comptent

Content-Security-Policy (CSP)

C'est la reine. Elle dit au navigateur depuis quelles origines il peut charger des scripts, des styles, des images, des polices et des connexions. Si un attaquant parvient à injecter un <script> dans ta page, une CSP bien faite l'empêche de s'exécuter. Un point de départ honnête pour une app moderne :

Content-Security-Policy: default-src 'self'; script-src 'self' https://js.stripe.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src 'self' https://*.supabase.co; frame-ancestors 'none'; base-uri 'self'; form-action 'self'

L'erreur typique est de mettre 'unsafe-inline' dans script-src parce que « sinon ça ne marche pas » : ça détruit la protection principale. Les frameworks modernes gèrent les scripts inline avec un nonce (une valeur aléatoire par requête) ou avec des hachages. Et la façon sûre de commencer, c'est le mode rapport : l'en-tête Content-Security-Policy-Report-Only ne bloque rien, il te raconte seulement ce qu'il bloquerait. Laisse-le ainsi quelques jours, examine les rapports et passe à l'en-tête réel quand il ne casse plus rien.

Strict-Transport-Security (HSTS)

Il oblige le navigateur à utiliser HTTPS pendant la durée indiquée, même si l'utilisateur tape http:// ou clique sur un vieux lien. Il empêche quelqu'un sur le même réseau de dégrader la connexion. La valeur habituelle :

Strict-Transport-Security: max-age=31536000; includeSubDomains

Active-le seulement quand tout ton domaine et ses sous-domaines passent par HTTPS : si tu le mets avec un sous-domaine encore en HTTP, tu le rends inaccessible pendant un an dans tous les navigateurs qui l'ont vu. Commence avec un max-age court en cas de doute.

X-Frame-Options et frame-ancestors

Ils empêchent ton site de se charger dans un <iframe> d'une autre page. Sans eux, quelqu'un peut intégrer ton app dans un faux site et pousser les utilisateurs à cliquer là où il ne faut pas : c'est le clickjacking. X-Frame-Options: DENY ou SAMEORIGIN règle le problème dans les anciens navigateurs ; la forme moderne est la directive frame-ancestors dans la CSP. Mets les deux.

X-Content-Type-Options

Une seule valeur : nosniff. Elle empêche le navigateur de deviner le type d'un fichier et d'exécuter comme un script quelque chose que tu as servi comme texte ou image. C'est une ligne ; aucune excuse pour l'oublier.

Referrer-Policy

Il contrôle quelle part de l'URL d'origine est envoyée quand on navigue vers un autre site ou qu'on charge une ressource externe. Sans contrôle, tu peux laisser fuir des chemins privés ou des tokens qui voyagent dans l'URL. strict-origin-when-cross-origin est l'équilibre raisonnable : ton domaine oui, le chemin complet non.

Permissions-Policy

Il déclare quelles capacités du navigateur ta page et ses iframes peuvent utiliser : caméra, micro, géolocalisation, paiements. Si tu ne les utilises pas, désactive-les ; ainsi un script injecté ou un iframe tiers ne pourra pas non plus. Par exemple : camera=(), microphone=(), geolocation=().

Cross-Origin-Opener-Policy

Moins connu : il isole ta fenêtre de celles qui l'ont ouverte ou que tu as ouvertes avec window.open, ce qui coupe une famille d'attaques entre onglets. same-origin est la valeur habituelle, sauf si tu dépends de fenêtres pop-up tierces (certains logins OAuth), où same-origin-allow-popups est préférable.

Ceux qu'il vaut mieux retirer

X-Powered-By et un en-tête Server avec version annoncent ta stack exacte à qui cherche des failles connues. Dans Next.js, on le retire avec poweredByHeader: false ; dans Express, avec app.disable('x-powered-by'). Et X-XSS-Protection est obsolète : les navigateurs modernes l'ignorent et dans les anciens il a causé des bugs. Ne le mets pas, ou mets-le à 0.

Comment les mettre selon ton hébergeur

Vercel, pour n'importe quel framework, dans vercel.json :

{
  "headers": [
    {
      "source": "/(.*)",
      "headers": [
        { "key": "Strict-Transport-Security", "value": "max-age=31536000; includeSubDomains" },
        { "key": "X-Frame-Options", "value": "SAMEORIGIN" },
        { "key": "X-Content-Type-Options", "value": "nosniff" },
        { "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" },
        { "key": "Permissions-Policy", "value": "camera=(), microphone=(), geolocation=()" }
      ]
    }
  ]
}

Next.js : la fonction headers() de next.config.js, avec la même liste ; la CSP avec nonce se génère dans le middleware. Nuxt : routeRules dans nuxt.config.ts avec un objet headers, ou un plugin serveur si tu as besoin d'un nonce. Netlify : un fichier _headers dans le dossier publié :

/*
  Strict-Transport-Security: max-age=31536000; includeSubDomains
  X-Frame-Options: SAMEORIGIN
  X-Content-Type-Options: nosniff
  Referrer-Policy: strict-origin-when-cross-origin

Cloudflare : des règles de transformation des en-têtes de réponse dans le tableau de bord, sans toucher au code. nginx sur un VPS :

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;

Je laisse la CSP hors de ces blocs exprès : c'est la seule qui dépend des scripts et services qu'utilise ton app, et il vaut mieux la construire en mode rapport avant de la figer.

Les erreurs qui cassent des choses

  • HSTS avant d'avoir tout en HTTPS. Il exclut quiconque a encore un sous-domaine en HTTP. Vérifie d'abord, active ensuite.
  • CSP sans nonce sur Next.js ou Nuxt. Les deux injectent des scripts inline pour hydrater la page ; sans nonce, une CSP stricte les bloque et l'app reste blanche. Utilise le mécanisme de nonce du framework.
  • En-têtes seulement sur le HTML. Les routes d'API et les fichiers statiques en ont besoin aussi, surtout nosniff. Applique la règle à /(.*).
  • En-têtes en double. Si le CDN et l'app ajoutent le même, le navigateur peut garder le plus strict ou ignorer les deux. Choisis un seul endroit.
  • Oublier les sous-domaines (app., api., docs.) : chacun répond avec ses propres en-têtes.

Vérifie-les depuis l'extérieur

Ces en-têtes sont des informations publiques : n'importe qui peut les lire, toi compris. Le vérificateur gratuit d'en-têtes te liste ceux qui manquent et ceux qui sont mal réglés en quelques secondes. Et Scanaris fait la vérification complète en lecture seule, avec environ 45 autres choses, et pour chaque en-tête absent te donne un fix prompt prêt à coller dans ton IA avec la ligne exacte pour ton hébergeur. Il n'exploite rien et ne touche pas à ton serveur : il lit et te dit quoi activer. Pour le contexte complet, voir le guide de sécurité des apps créées par IA et la checklist de lancement.

Questions fréquentes

Les en-têtes ralentissent-ils le site ?

Non. Ce sont quelques centaines d'octets par réponse et le navigateur les traite en microsecondes. HSTS l'accélère même, parce qu'il évite la redirection de HTTP vers HTTPS lors des visites suivantes.

Que se passe-t-il si un en-tête casse quelque chose en production ?

Retire-le ou assouplis-le et redéploie : l'effet est immédiat, sauf pour HSTS, que les navigateurs mémorisent pendant le max-age. C'est pour ça que la CSP se teste en mode rapport et que HSTS s'active en dernier.

Ai-je besoin d'une CSP si mon app est petite ?

Si ton app a un formulaire ou affiche du contenu d'utilisateurs, oui : c'est la défense qui transforme un XSS en incident mineur. Commence par les autres en-têtes, qui sont triviaux, et ajoute la CSP en mode rapport quand tu peux y consacrer un après-midi.

Comment se porte ton site ?

Passe-lui Scanaris et vérifie en 30 secondes, c'est gratuit.

Analyser mon site

Vérifications liées