OWASP & AppSec

Security headers HTTP : lesquels, pourquoi, guide complet

Guide complet security headers HTTP : CSP, HSTS, X-Frame-Options, Permissions-Policy, COOP/COEP/CORP, Referrer-Policy. Rôle, configuration, pièges, tests.

Naim Aouaichia
18 min de lecture
  • Security Headers
  • CSP
  • HSTS
  • OWASP
  • Configuration web
  • Secure coding
  • Headers HTTP

Les security headers HTTP sont des en-têtes de réponse configurés côté serveur pour instruire le navigateur sur les politiques de sécurité à appliquer. 13 headers structurent une posture moderne en 2026, dont 7 critiques : Content-Security-Policy (CSP), Strict-Transport-Security (HSTS), X-Frame-Options / frame-ancestors (anti-clickjacking), X-Content-Type-Options (anti-MIME sniffing), Referrer-Policy, Permissions-Policy, Cross-Origin-Opener-Policy (COOP). Les stacks modernes ajoutent COEP et CORP pour isolation cross-origin complète, indispensable aux APIs sensibles (SharedArrayBuffer). CSP est le plus important : configurée strictement avec nonce dynamique, elle bloque 90 % des XSS exploitables. HSTS force HTTPS avec preload pour résistance maximale. Les headers Secure, HttpOnly, SameSite sur cookies complètent la protection. Déploiement en production recommandé via mode Report-Only pendant 3-6 mois avant enforcement pour éviter les régressions. Tests outillés : securityheaders.com, Mozilla Observatory, Burp Scanner, testssl.sh. Cet article est un guide exhaustif : rôle détaillé de chaque header, configurations recommandées 2026, pièges courants, exemples Nginx / Apache / Node.js helmet / Cloudflare, et méthodologie de test.

1. Vue d'ensemble des 13 security headers

Tableau de référence des headers à connaître, classés par priorité opérationnelle.

#HeaderPrioritéRôle principal
1Content-Security-Policy (CSP)CritiqueAnti-XSS, anti-injection scripts/ressources
2Strict-Transport-Security (HSTS)CritiqueForcer HTTPS, anti-downgrade
3X-Frame-Options / frame-ancestorsCritiqueAnti-clickjacking
4X-Content-Type-Options: nosniffÉlevéeDésactive MIME sniffing
5Referrer-PolicyÉlevéeContrôle du referer (vie privée + sécu)
6Permissions-Policy (ex Feature-Policy)ÉlevéeRestriction des APIs navigateur
7Cross-Origin-Opener-Policy (COOP)ÉlevéeIsolation window cross-origin
8Cross-Origin-Embedder-Policy (COEP)MoyenneOpt-in cross-origin embedding
9Cross-Origin-Resource-Policy (CORP)MoyenneRestriction chargement cross-origin
10Clear-Site-DataMoyenneNettoyage données à logout
11Cache-Control / Pragma / ExpiresMoyenneAnti-cache pages sensibles
12X-XSS-Protection (déprécié)LegacyAnciens browsers, obsolète
13X-Permitted-Cross-Domain-PoliciesLegacyFlash / PDF cross-domain

Stratégie de déploiement : déployer dans l'ordre de priorité, en mode Report-Only pour CSP, et valider via outils de test avant enforcement.

2. Les 3 headers critiques : CSP, HSTS, anti-framing

Content-Security-Policy (CSP), le plus important

Rôle : restreint les sources de scripts, styles, images, fonts, frames, formulaires, etc. que le navigateur est autorisé à charger et exécuter. Protection principale contre XSS (Cross-Site Scripting) et injections de contenu.

Syntaxe : liste de directives séparées par ;. Chaque directive définit une catégorie de ressource et ses sources autorisées.

CSP stricte recommandée en 2026 (avec nonce) :

Content-Security-Policy: default-src 'self';
  script-src 'self' 'nonce-RANDOM_BYTES_BASE64';
  style-src 'self' 'unsafe-inline';
  img-src 'self' data: https:;
  font-src 'self';
  connect-src 'self';
  media-src 'self';
  object-src 'none';
  frame-src 'self';
  frame-ancestors 'none';
  base-uri 'self';
  form-action 'self';
  upgrade-insecure-requests;
  block-all-mixed-content;
  report-uri https://example.fr/csp-report;
  report-to csp-endpoint

Principales directives à comprendre :

  • default-src 'self' : valeur de repli pour toute directive non spécifiée. 'self' autorise uniquement la même origine.
  • script-src : sources de scripts JS. Utiliser 'nonce-X' pour les scripts inline légitimes (nonce régénéré à chaque requête, 16+ bytes aléatoires).
  • style-src : sources de styles CSS. 'unsafe-inline' parfois nécessaire pour inline styles (moins dangereux que script).
  • img-src : sources d'images. data: autorise les images base64 inline, https: autorise toutes les images HTTPS.
  • connect-src : destinations fetch/XHR/WebSocket. Restreint les exfiltrations.
  • object-src 'none' : désactive <object>, <embed>, presque toujours sûr, recommandé.
  • frame-ancestors 'none' : remplace X-Frame-Options DENY (moderne, recommandé).
  • base-uri 'self' : empêche manipulation de <base> pour rediriger les URLs relatives.
  • form-action 'self' : restreint les destinations des formulaires.
  • upgrade-insecure-requests : force HTTP vers HTTPS pour toutes les sous-ressources.
  • report-uri / report-to : endpoint de reporting des violations CSP.

Mode Report-Only pour déploiement progressif :

Content-Security-Policy-Report-Only: default-src 'self'; ...; report-uri /csp-report

En mode Report-Only, le navigateur n'applique pas la policy mais envoie des rapports de violation. Permet de tester la CSP en production sans bloquer les utilisateurs. Durée typique : 3-6 mois d'observation avant passage en enforcement.

Génération nonce côté serveur (Node.js Express) :

// Generation nonce CSP cote serveur
import crypto from 'crypto';
 
app.use((req, res, next) => {
  const nonce = crypto.randomBytes(16).toString('base64');
  res.locals.cspNonce = nonce;
  res.setHeader(
    'Content-Security-Policy',
    `default-src 'self'; ` +
    `script-src 'self' 'nonce-${nonce}'; ` +
    `style-src 'self' 'unsafe-inline'; ` +
    `img-src 'self' data: https:; ` +
    `font-src 'self'; ` +
    `connect-src 'self'; ` +
    `object-src 'none'; ` +
    `frame-ancestors 'none'; ` +
    `base-uri 'self'; ` +
    `form-action 'self'; ` +
    `upgrade-insecure-requests`
  );
  next();
});

Pour la vulnérabilité XSS que la CSP protège principalement, voir Vulnérabilité XSS : explication complète pour comprendre.

Strict-Transport-Security (HSTS), forcer HTTPS

Rôle : instruit le navigateur à ne jamais se connecter au site en HTTP, même si l'utilisateur tape l'URL en HTTP. Protège contre les attaques downgrade et SSL stripping (man-in-the-middle).

Syntaxe recommandée 2026 :

Strict-Transport-Security: max-age=63072000; includeSubDomains; preload

Décomposition :

  • max-age=63072000 : durée en secondes de validité de la directive (ici 2 ans). Recommandation 1-2 ans après validation.
  • includeSubDomains : étend la politique à tous les sous-domaines. Attention : si un sous-domaine doit rester HTTP, ne pas inclure.
  • preload : autorise l'inclusion du domaine dans la HSTS Preload List (liste intégrée nativement dans Chrome, Firefox, Safari, Edge). Préchargement = HTTPS forcé dès le premier accès, même avant réception du header.

Processus d'inscription à la HSTS Preload List :

  1. Déployer HSTS avec max-age=31536000; includeSubDomains; preload pendant 1+ mois sans incident.
  2. Soumettre le domaine sur hstspreload.org.
  3. Attendre 4-8 semaines pour l'inclusion dans les builds navigateur.

Piège : une fois sur la HSTS Preload List, retrait quasi impossible (6-12 mois minimum). Ne jamais activer HSTS sans certitude d'avoir HTTPS stable sur le domaine et tous sous-domaines concernés.

Anti-framing : X-Frame-Options et frame-ancestors CSP

Rôle : protéger contre le clickjacking (UI redressing). Un attaquant intègre le site cible dans un iframe qu'il dissimule, et incite la victime à cliquer sur des zones masquées qui correspondent à des boutons sensibles (changement de mot de passe, transfert d'argent).

X-Frame-Options (legacy, 2010) :

X-Frame-Options: DENY

Ou :

X-Frame-Options: SAMEORIGIN

Valeurs : DENY (jamais framé), SAMEORIGIN (même origine OK). ALLOW-FROM uri est déprécié et ignoré par les navigateurs modernes.

frame-ancestors (CSP, moderne et recommandé) :

Content-Security-Policy: frame-ancestors 'none'
# ou
Content-Security-Policy: frame-ancestors 'self'
# ou
Content-Security-Policy: frame-ancestors https://trusted.example.com

Recommandation 2026 : utiliser frame-ancestors dans la CSP, X-Frame-Options en fallback pour navigateurs legacy. Les navigateurs modernes (Chrome, Firefox, Safari, Edge) donnent priorité à frame-ancestors quand les deux sont présents.

3. Headers anti-sniffing et Referrer-Policy

X-Content-Type-Options: nosniff

Rôle : désactive le MIME sniffing du navigateur. Sans ce header, certains navigateurs devinent le type MIME d'une ressource en analysant son contenu, ignorant le Content-Type déclaré par le serveur. Problème sécurité : un fichier texte contenant du JavaScript peut être exécuté comme script si le navigateur « devine » que c'est du JS.

Valeur unique :

X-Content-Type-Options: nosniff

Impact : le navigateur respecte strictement le Content-Type déclaré. Un fichier .txt servi avec Content-Type: text/plain ne sera jamais exécuté comme JavaScript, même s'il contient du code JS.

Recommandation : toujours activer. Pas de configuration complexe, compatibilité universelle.

Referrer-Policy

Rôle : contrôle l'envoi du header Referer quand l'utilisateur navigue depuis le site vers une autre origine. Protège à la fois la vie privée (ne pas divulguer les URL internes sensibles) et la sécurité (ne pas fuiter des tokens présents dans les URL).

Valeurs possibles (de la moins à la plus restrictive) :

ValeurComportement
no-referrerAucun referer envoyé
no-referrer-when-downgradeReferer envoyé sauf HTTPS vers HTTP
originEnvoie uniquement l'origine (schéma + host + port)
origin-when-cross-originURL complète en same-origin, origine seule en cross-origin
same-originReferer envoyé uniquement en same-origin
strict-originOrigine envoyée sauf HTTPS vers HTTP
strict-origin-when-cross-originDéfaut moderne recommandé
unsafe-urlURL complète toujours (déconseillé)

Recommandation 2026 :

Referrer-Policy: strict-origin-when-cross-origin

Pour les sites avec données très sensibles (santé, banque, identité) :

Referrer-Policy: no-referrer

4. Permissions-Policy et headers Cross-Origin

Permissions-Policy (ex Feature-Policy)

Rôle : restreint l'accès des APIs navigateur sensibles (géolocalisation, caméra, micro, paiement, USB, capteurs) depuis la page et ses iframes. Renommé de Feature-Policy en 2020.

Syntaxe : liste de feature=(allowlist) séparés par ,.

Configuration restrictive recommandée :

Permissions-Policy: accelerometer=(),
  ambient-light-sensor=(),
  autoplay=(),
  battery=(),
  camera=(),
  cross-origin-isolated=(),
  display-capture=(),
  document-domain=(),
  encrypted-media=(),
  execution-while-not-rendered=(),
  execution-while-out-of-viewport=(),
  fullscreen=(self),
  geolocation=(),
  gyroscope=(),
  keyboard-map=(),
  magnetometer=(),
  microphone=(),
  midi=(),
  navigation-override=(),
  payment=(),
  picture-in-picture=(),
  publickey-credentials-get=(),
  screen-wake-lock=(),
  sync-xhr=(),
  usb=(),
  web-share=(),
  xr-spatial-tracking=()

Principes :

  • () = refusé partout.
  • (self) = autorisé sur la même origine uniquement.
  • (self "https://trusted.example.com") = autorisé sur origines spécifiques.
  • * = autorisé partout (très permissif, déconseillé).

Adaptation au cas d'usage : autoriser geolocation=(self) pour une app cartographique, camera=(self) pour une app vidéoconférence, etc. Tout ce qui n'est pas utilisé doit être bloqué par =().

Cross-Origin-Opener-Policy (COOP)

Rôle : isole la window du document courant des autres windows ouvertes cross-origin, empêchant les références croisées (window.opener, window.postMessage). Fondamental pour l'isolation des contextes sensibles.

Valeurs :

ValeurComportement
unsafe-nonePas d'isolation (défaut historique)
same-origin-allow-popupsIsolation sauf popups ouvertes par le document
same-originIsolation complète recommandée

Recommandation 2026 :

Cross-Origin-Opener-Policy: same-origin

Impact : bloque les attaques Spectre-like basées sur l'analyse des timings cross-origin. Indispensable pour activer les APIs sensibles SharedArrayBuffer et performance.measureUserAgentSpecificMemory (combiné à COEP).

Cross-Origin-Embedder-Policy (COEP)

Rôle : exige que toutes les ressources embarquées (images, scripts, fonts, workers) déclarent explicitement leur politique cross-origin. Bloque les ressources sans opt-in explicite.

Valeurs :

  • unsafe-none : pas d'exigence (défaut).
  • require-corp : exige que chaque ressource envoie Cross-Origin-Resource-Policy explicite.
  • credentialless (récent) : compromis permettant de charger les ressources cross-origin sans credentials.

Recommandation pour apps sensibles :

Cross-Origin-Embedder-Policy: require-corp

Prérequis : toutes les ressources tierces embarquées (CDN, fonts Google, widgets analytics) doivent envoyer Cross-Origin-Resource-Policy: cross-origin ou équivalent. Sinon elles sont bloquées. Migration vers COEP demande 3-6 mois typique.

Cross-Origin-Resource-Policy (CORP)

Rôle : le serveur déclare qui peut charger sa ressource. Complément obligatoire de COEP require-corp.

Valeurs :

  • same-site : chargement autorisé depuis les domaines du même site (eTLD+1).
  • same-origin : chargement autorisé depuis la même origine exclusivement.
  • cross-origin : chargement autorisé depuis n'importe quelle origine.

Exemple :

Cross-Origin-Resource-Policy: same-site

Cas d'usage : un CDN qui sert des ressources à multiples domaines partenaires utilise cross-origin. Une API interne privée utilise same-origin.

5. Headers cookies et Clear-Site-Data

Les cookies ne sont pas un « header » au sens strict mais sont configurés via Set-Cookie avec des attributs critiques.

Exemple de cookie de session sécurisé :

Set-Cookie: sessionId=AbCdEf123; Secure; HttpOnly; SameSite=Lax; Max-Age=3600; Path=/; Domain=.example.fr

Attributs critiques :

AttributRôle
SecureCookie envoyé uniquement sur HTTPS
HttpOnlyCookie inaccessible via JavaScript (protection XSS)
SameSite=LaxCookie envoyé en GET cross-site top-level seul (protection CSRF)
SameSite=StrictCookie envoyé uniquement en same-site (maximum CSRF protection)
SameSite=NoneCookie envoyé cross-site (requiert Secure)
Max-AgeDurée de vie en secondes
PathChemin où le cookie est envoyé
DomainDomaines qui reçoivent le cookie
__Host- prefixForce Path=/, pas de Domain, Secure obligatoire

Recommandation 2026 pour cookies de session :

Set-Cookie: __Host-session=TOKEN; Secure; HttpOnly; SameSite=Lax; Path=/; Max-Age=3600

Le préfixe __Host- impose trois contraintes (Secure, pas de Domain, Path=/) et protège contre les cookie tossing attacks.

Clear-Site-Data

Rôle : instruit le navigateur de nettoyer les données stockées (cookies, storage, cache) pour l'origine. Utilisé typiquement à la déconnexion pour effacement complet.

Exemple lors du logout :

Clear-Site-Data: "cookies", "storage", "cache"

Valeurs :

  • "cookies" : supprime tous les cookies de l'origine.
  • "storage" : supprime localStorage, sessionStorage, IndexedDB, Cache API.
  • "cache" : vide le cache HTTP.
  • "executionContexts" : réinitialise les contextes d'exécution (workers, etc.).
  • "*" : tout ce qui précède.

Cache-Control pour pages sensibles

Les pages contenant des données sensibles (backoffice, données personnelles, paiement) ne doivent jamais être cachées ni par le navigateur ni par des proxies intermédiaires.

Cache-Control: no-store, no-cache, must-revalidate, private
Pragma: no-cache
Expires: 0

Important : Cache-Control: no-store est la directive moderne la plus restrictive. Les autres (Pragma, Expires) sont des fallbacks pour proxies legacy HTTP/1.0.

6. Headers à supprimer et headers historiques

Headers à supprimer (information disclosure)

Certains headers fuitent des informations utiles à un attaquant et doivent être supprimés ou neutralisés :

  • Server : version du serveur web (Apache/2.4.52, nginx/1.22.0). Utile pour exploiter des CVE spécifiques.
  • X-Powered-By : framework backend (Express, PHP/7.4.3). Même problème.
  • X-AspNet-Version : version .NET.
  • X-Generator : CMS et version (WordPress, Drupal, Joomla).

Nginx, masquage headers :

server_tokens off;
more_clear_headers 'Server';
proxy_hide_header X-Powered-By;

Node.js Express, masquage :

app.disable('x-powered-by');
// Helmet le fait par defaut

Headers historiques dépréciés

  • X-XSS-Protection : déprécié, les navigateurs modernes ont abandonné les filtres XSS intégrés (trop de bypass). Valeur 0 recommandée pour désactiver les implémentations legacy restantes.
X-XSS-Protection: 0
  • X-Download-Options: noopen : spécifique à IE, limite l'ouverture directe de fichiers téléchargés. Peu utile en 2026.
  • X-Permitted-Cross-Domain-Policies: none : spécifique à Flash et PDF Adobe, utile uniquement si ces technologies sont servies.

7. Tests et configuration par stack

Outils de test

Tests en ligne gratuits :

  • securityheaders.com (Scott Helme) : grade A+ à F avec recommandations détaillées, référence de la communauté.
  • Mozilla Observatory : score 0-135 avec 11 tests et explications par header.
  • CSP Evaluator (Google) : analyse spécifique CSP avec détection des weakness patterns.
  • HSTS Preload Status (hstspreload.org) : vérifie éligibilité et statut HSTS Preload List.

Outils CLI et automation :

# Test rapide des headers via curl
curl -I https://example.fr
 
# Test headers complet avec output colorise
curl -sI https://example.fr | awk '/^[A-Z]/ {print}'
 
# Test TLS + headers via testssl.sh
testssl.sh --headers https://example.fr
 
# Test headers automatise via Python
python3 -c "import requests; r = requests.head('https://example.fr'); [print(f'{k}: {v}') for k, v in r.headers.items()]"

Tests en CI/CD :

# Exemple test security headers dans GitHub Actions
name: Security Headers Check
on: [push]
jobs:
  check-headers:
    runs-on: ubuntu-latest
    steps:
      - name: Check production headers
        run: |
          curl -sI https://example.fr > headers.txt
          grep -q "Content-Security-Policy" headers.txt || exit 1
          grep -q "Strict-Transport-Security" headers.txt || exit 1
          grep -q "X-Content-Type-Options: nosniff" headers.txt || exit 1
          grep -q "Referrer-Policy" headers.txt || exit 1
          echo "All critical headers present"

Configuration Nginx

Configuration complète Nginx 2026 avec tous les security headers critiques :

# /etc/nginx/conf.d/security-headers.conf
# A inclure dans chaque server block
 
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; object-src 'none'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'; upgrade-insecure-requests" always;
 
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
 
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=(), payment=()" always;
add_header Cross-Origin-Opener-Policy "same-origin" always;
add_header Cross-Origin-Resource-Policy "same-site" always;
 
# Masquage information disclosure
server_tokens off;
more_clear_headers 'X-Powered-By';
 
# Desactivation XSS-Protection legacy
add_header X-XSS-Protection "0" always;

Configuration Apache

# /etc/apache2/conf-available/security-headers.conf
# a2enconf security-headers
 
<IfModule mod_headers.c>
  Header always set Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; object-src 'none'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'; upgrade-insecure-requests"
 
  Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
  Header always set X-Frame-Options "DENY"
  Header always set X-Content-Type-Options "nosniff"
  Header always set Referrer-Policy "strict-origin-when-cross-origin"
  Header always set Permissions-Policy "geolocation=(), microphone=(), camera=(), payment=()"
  Header always set Cross-Origin-Opener-Policy "same-origin"
  Header always set Cross-Origin-Resource-Policy "same-site"
  Header always set X-XSS-Protection "0"
 
  # Masquage
  Header unset X-Powered-By
  Header unset Server
</IfModule>
 
ServerTokens Prod
ServerSignature Off

Configuration Node.js avec Helmet

// Node.js Express avec helmet
import express from 'express';
import helmet from 'helmet';
import crypto from 'crypto';
 
const app = express();
 
// Generation nonce par requete pour CSP
app.use((req, res, next) => {
  res.locals.cspNonce = crypto.randomBytes(16).toString('base64');
  next();
});
 
app.use(
  helmet({
    contentSecurityPolicy: {
      directives: {
        defaultSrc: ["'self'"],
        scriptSrc: ["'self'", (req, res) => `'nonce-${res.locals.cspNonce}'`],
        styleSrc: ["'self'", "'unsafe-inline'"],
        imgSrc: ["'self'", 'data:', 'https:'],
        fontSrc: ["'self'"],
        connectSrc: ["'self'"],
        objectSrc: ["'none'"],
        frameAncestors: ["'none'"],
        baseUri: ["'self'"],
        formAction: ["'self'"],
        upgradeInsecureRequests: [],
      },
    },
    strictTransportSecurity: {
      maxAge: 63072000,
      includeSubDomains: true,
      preload: true,
    },
    frameguard: { action: 'deny' },
    referrerPolicy: { policy: 'strict-origin-when-cross-origin' },
    crossOriginOpenerPolicy: { policy: 'same-origin' },
    crossOriginResourcePolicy: { policy: 'same-site' },
    xContentTypeOptions: true,
    xXssProtection: false,
  })
);
 
// Permissions-Policy (pas dans helmet par defaut)
app.use((req, res, next) => {
  res.setHeader(
    'Permissions-Policy',
    'geolocation=(), microphone=(), camera=(), payment=()'
  );
  next();
});
 
app.disable('x-powered-by');

Configuration Cloudflare

Cloudflare permet de configurer les security headers via Transform Rules ou Response Header Modification.

Interface Cloudflare > Rules > Transform Rules > Modify Response Header :

Condition: hostname equals example.fr
Action: Set dynamic
 
Header name: Content-Security-Policy
Header value: "default-src 'self'; script-src 'self'; ... ; upgrade-insecure-requests"
 
Header name: Strict-Transport-Security
Header value: "max-age=63072000; includeSubDomains; preload"
 
# Etc pour chaque header critique

Avantage Cloudflare : configuration sans modifier le serveur d'origine, applicable globalement sur tous les chemins du domaine. Peut aussi compléter la config serveur (belt-and-braces).

Stratégie de déploiement progressif recommandée

Déploiement en 4 phases typique pour éviter les régressions en production.

PhaseDuréeAction
Phase 1, Audit initial1-2 semainesTester la configuration actuelle via securityheaders.com + Mozilla Observatory, documenter le gap
Phase 2, Headers simples2-4 semainesDéployer HSTS, X-Content-Type-Options, X-Frame-Options, Referrer-Policy (peu de risque de régression)
Phase 3, CSP Report-Only3-6 moisDéployer CSP en Content-Security-Policy-Report-Only, observer les violations, ajuster la policy
Phase 4, CSP enforcementDéfinitifBasculer CSP en enforcement, ajouter COOP/COEP/CORP pour isolation renforcée

Points clés à retenir

  • 13 security headers structurent une posture moderne, dont 7 critiques : CSP, HSTS, X-Frame-Options / frame-ancestors, X-Content-Type-Options, Referrer-Policy, Permissions-Policy, COOP.
  • CSP (Content-Security-Policy) = le plus important, bloque 90 % des XSS exploitables en configuration stricte. Utiliser nonce dynamique, éviter 'unsafe-inline' sur script-src.
  • HSTS avec preload force HTTPS de manière permanente via les navigateurs (max-age 2 ans, includeSubDomains, preload).
  • Cookies sécurisés : Secure, HttpOnly, SameSite=Lax minimum. Préfixe __Host- pour sessions critiques.
  • COOP + COEP + CORP : isolation cross-origin complète, nécessaire pour activer SharedArrayBuffer et APIs sensibles.
  • Permissions-Policy : bloque systématiquement toutes les APIs non utilisées (camera, micro, géolocalisation, USB, paiement).
  • Déploiement progressif en 4 phases : audit, headers simples, CSP Report-Only 3-6 mois, puis enforcement.
  • Tests outillés : securityheaders.com, Mozilla Observatory, CSP Evaluator, testssl.sh, Burp Scanner.

Pour comprendre l'attaque XSS que la CSP protège principalement, voir Vulnérabilité XSS : explication complète pour comprendre. Pour le contexte OWASP Top 10 dont les security headers adressent plusieurs catégories (A02 Cryptographic Failures, A03 Injection, A05 Security Misconfiguration, A07 Auth Failures), voir Introduction à l'OWASP Top 10. Pour la méthodologie pentest web qui inclut l'audit des security headers dans la phase d'exploitation, voir Qu'est-ce qu'un pentest web ? Définition, méthode, outils. Pour le rôle AppSec engineer qui définit et maintient la configuration des security headers dans une application, voir Qu'est-ce qu'un AppSec engineer ? Fiche métier. Pour le rôle DevSecOps qui intègre les tests de security headers en CI/CD, voir Qu'est-ce qu'un DevSecOps ? Fiche métier complète. La formation OWASP Web Security de Zeroday couvre la configuration des security headers avec labs pratiques : déploiement Nginx durci, CSP stricte avec nonce, migration Report-Only vers enforcement, tests securityheaders.com et Mozilla Observatory.

Questions fréquentes

  • Quels sont les security headers HTTP essentiels à configurer en 2026 ?
    Sept headers prioritaires. 1) Content-Security-Policy (CSP) : protège contre XSS et injections, complexe mais essentiel. 2) Strict-Transport-Security (HSTS) : force HTTPS, protège contre downgrade attacks. 3) X-Frame-Options ou frame-ancestors en CSP : protège contre clickjacking. 4) X-Content-Type-Options: nosniff : désactive MIME sniffing. 5) Referrer-Policy : contrôle l'envoi du referer (vie privée). 6) Permissions-Policy (ex Feature-Policy) : restreint les APIs navigateur (géolocalisation, caméra, micro). 7) Cross-Origin-Opener-Policy (COOP) : isole les window cross-origin. Stack moderne ajoute COEP et CORP pour isolation complète.
  • Comment configurer une Content Security Policy (CSP) efficace ?
    CSP stricte recommandée 2026 : default-src self ; script-src self plus nonce aléatoire ; style-src self ; img-src self plus data HTTPS ; font-src self ; connect-src self ; frame-ancestors none ; base-uri self ; form-action self. Le nonce doit être régénéré aléatoirement à chaque requête (16+ bytes). Éviter unsafe-inline sur script-src (défait 80 % de la protection). Démarrer en mode Content-Security-Policy-Report-Only avec endpoint de report pour observer les violations avant enforcement. Durée typique de déploiement : 3 à 6 mois pour ajuster la policy en production.
  • Quelle différence entre X-Frame-Options et frame-ancestors CSP ?
    X-Frame-Options est l'ancien header (2010) supportant 3 valeurs : DENY (jamais framé), SAMEORIGIN (même origine OK), ALLOW-FROM uri (origine spécifique, déprécié par les navigateurs). La directive CSP frame-ancestors est plus moderne, flexible et recommandée : frame-ancestors none, self, ou liste d'origines. Les navigateurs modernes donnent priorité à frame-ancestors quand les deux sont présents. Recommandation 2026 : utiliser uniquement frame-ancestors dans la CSP, X-Frame-Options en fallback pour navigateurs legacy reste acceptable.
  • À quoi servent COOP, COEP et CORP ?
    Trois headers Cross-Origin introduits pour l'isolation renforcée. COOP (Cross-Origin-Opener-Policy) : isole la window du document des autres windows cross-origin. same-origin recommandé bloque les références window.open croisées. COEP (Cross-Origin-Embedder-Policy) : exige que toutes les ressources embarquées déclarent explicitement leur cross-origin policy. require-corp bloque les ressources sans opt-in. CORP (Cross-Origin-Resource-Policy) : ressources déclarent qui peut les charger : same-site, same-origin, cross-origin. Ensemble COOP plus COEP activent les APIs sensibles (SharedArrayBuffer, performance.measureUserAgentSpecificMemory).
  • Comment tester les security headers d'un site ?
    Quatre outils complémentaires. 1) securityheaders.com (Scott Helme) : analyse rapide en ligne, grade A+ à F, recommandations détaillées. 2) Mozilla Observatory : analyse approfondie avec 11 tests, score 0 à 135, explications par header. 3) Burp Suite Professional : Scanner détecte les headers manquants en mode active scan. 4) testssl.sh : CLI open source, focus TLS mais inclut les headers de sécurité principaux. Pour validation CI/CD : Node.js helmet offre des tests unitaires, ou scripts Python avec requests.head(). Tester tous les chemins authentifiés et non-authentifiés (souvent config diffère entre les deux).

Écrit par

Naim Aouaichia

Cyber Security Engineer et fondateur de Zeroday Cyber Academy

Ingénieur cybersécurité avec un parcours hybride : développement, DevOps Capgemini, DevSecOps IN Groupe (sécurité des documents d'identité régaliens), audits CAC 40. Fondateur de Hash24Security et Zeroday Cyber Academy. Présence LinkedIn 43 000 abonnés, Substack Zeroday Notes 23 000 abonnés.