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

Expert cybersécurité et fondateur de Zeroday Cyber Academy

Expert cybersécurité avec un master spécialisé et un parcours hybride : développement, DevOps, DevSecOps, SOC, GRC. Fondateur de Hash24Security et Zeroday Cyber Academy. Formateur et créateur de contenu technique sur la cybersécurité appliquée, la sécurité des LLM et le DevSecOps.