Module B01

Headers HTTP & Helmet

Sécurisez vos réponses HTTP avec les headers essentiels et automatisez-les avec Helmet.js.

01 Les headers de sécurité HTTP essentiels

Les headers HTTP de sécurité sont des directives envoyées par le serveur dans chaque réponse. Ils instruisent le navigateur sur la manière de traiter le contenu, réduisant la surface d'attaque côté client.

⚠️ Un serveur sans headers de sécurité expose ses utilisateurs au XSS, clickjacking, sniffing MIME, et fuites d'informations via le Referer.
HeaderRôleSans lui
Content-Security-PolicyContrôle les sources autorisées (scripts, styles, images…)XSS possible
Strict-Transport-SecurityForce HTTPS, mémorise la décisionDowngrade HTTP
X-Frame-OptionsEmpêche l'affichage dans une iframeClickjacking
X-Content-Type-OptionsEmpêche le MIME sniffingMIME confusion
Referrer-PolicyContrôle l'URL envoyée dans l'en-tête RefererFuite URL
Permissions-PolicyRestreint l'accès aux API navigateur (caméra, géoloc…)Abus API

02 Helmet.js — automatisation des headers

Helmet est un middleware Express qui configure automatiquement 11+ headers de sécurité en une seule ligne. C'est la première chose à ajouter sur tout projet Node.js.

const express = require('express');
const helmet = require('helmet');

const app = express();

// Active tous les middlewares Helmet par défaut
app.use(helmet());

// Ou personnalisé :
app.use(helmet({
  contentSecurityPolicy: {
    directives: {
      "default-src": ["'self'"],
      "script-src": ["'self'", "https://cdn.jsdelivr.net"],
      "img-src": ["'self'", "data:"],
    }
  },
  hsts: {
    maxAge: 31536000,
    includeSubDomains: true,
    preload: true
  }
}));

Middlewares activés par défaut

Middleware HelmetHeader configuréValeur par défaut
contentSecurityPolicyContent-Security-PolicyPolitique restrictive
hstsStrict-Transport-Securitymax-age=15552000
frameguardX-Frame-OptionsSAMEORIGIN
noSniffX-Content-Type-Optionsnosniff
referrerPolicyReferrer-Policyno-referrer
xssFilterX-XSS-Protection0 (désactivé, CSP suffit)
dnsPrefetchControlX-DNS-Prefetch-Controloff
permittedCrossDomainPoliciesX-Permitted-Cross-Domain-Policiesnone
hidePoweredByX-Powered-BySupprimé
ieNoOpenX-Download-Optionsnoopen
originAgentClusterOrigin-Agent-Cluster?1

03 Content-Security-Policy — directives, nonces, hashes

La CSP est le header le plus puissant pour contrer le XSS. Elle déclare une liste blanche des sources autorisées pour chaque type de ressource.

Directives essentielles

// Politique stricte pour une SPA React
Content-Security-Policy:
  default-src 'self';
  script-src 'self' 'nonce-abc123';
  style-src 'self' 'unsafe-inline';
  img-src 'self' data: https://images.example.com;
  font-src 'self' https://fonts.gstatic.com;
  connect-src 'self' https://api.example.com;
  object-src 'none';
  base-uri 'self';
  form-action 'self';
  frame-ancestors 'none';

Nonce vs Hash

TechniqueUsageExemple
NonceScript inline dynamique — token unique par requêtescript-src 'nonce-{random}'
HashScript inline statique — hash SHA256 du contenuscript-src 'sha256-abc...'
'unsafe-inline'Autorise tous les scripts inline — à éviterDangereux
// Générer un nonce côté serveur (Express)
const crypto = require('crypto');

app.use((req, res, next) => {
  res.locals.nonce = crypto.randomBytes(16).toString('base64');
  next();
});

// Dans le template EJS :
// <script nonce="<%= nonce %>"> ... </script>

04 HSTS — Strict-Transport-Security

HSTS force le navigateur à utiliser HTTPS pour toutes les futures requêtes vers un domaine, même si l'utilisateur tape http://. La directive max-age définit la durée de mémorisation en secondes.

// Header optimal
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

// Avec Helmet :
helmet({
  hsts: {
    maxAge: 31536000,       // 1 an en secondes
    includeSubDomains: true, // Couvre *.example.com
    preload: true            // Permet l'inclusion dans le navigateur preload list
  }
})
⚠️ Ne jamais activer HSTS avant d'avoir un certificat TLS valide — vous bloquerez l'accès HTTP sans fallback possible pendant toute la durée max-age.

HSTS Preloading

Le preloading inscrit votre domaine dans une liste embarquée dans Chrome, Firefox, Safari. Même la toute première requête HTTP est refusée par le navigateur. Pour s'inscrire : hstspreload.org.

05 X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy

X-Frame-Options

Empêche le chargement de votre page dans une <iframe>, bloquant le clickjacking.

X-Frame-Options: DENY          // Aucune iframe autorisée
X-Frame-Options: SAMEORIGIN    // Iframe autorisée sur le même domaine seulement
// Note : frame-ancestors dans CSP est plus flexible et moderne
Content-Security-Policy: frame-ancestors 'self' https://admin.example.com;

X-Content-Type-Options

Empêche le navigateur de deviner (sniff) le Content-Type d'une réponse. Sans ce header, un fichier texte uploadé peut être interprété comme JavaScript.

X-Content-Type-Options: nosniff   // Seule valeur valide

Referrer-Policy

Contrôle quelles informations sont incluses dans l'en-tête Referer des requêtes sortantes.

ValeurComportement
no-referrerJamais d'info envoyée
strict-originEnvoie seulement l'origine (domaine), pas le chemin
strict-origin-when-cross-originChemin complet intra-site, domaine seul cross-site
unsafe-urlTout envoyer — dangereux

Permissions-Policy

Remplace l'ancien Feature-Policy. Restreint l'accès aux fonctionnalités navigateur pour votre page et les iframes embarquées.

Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=()
// Désactive caméra, micro, géolocalisation et paiement pour toutes les origines

// Avec Helmet :
helmet({
  permissionsPolicy: {
    features: {
      camera: [""],
      microphone: [""],
      geolocation: [""],
    }
  }
})