Headers HTTP sécurisés
Configuration des en-têtes HTTP pour protéger les applications web contre les attaques courantes (XSS, clickjacking, MIME sniffing, etc.).
Vue d’ensemble
| En-tête | Protection | Valeur recommandée |
|---|---|---|
Content-Security-Policy | XSS, injection | Politique restrictive adaptée à l’appli |
X-Frame-Options | Clickjacking | DENY ou SAMEORIGIN |
X-Content-Type-Options | MIME sniffing | nosniff |
Referrer-Policy | Fuites de données | strict-origin-when-cross-origin |
Permissions-Policy | Contrôle des APIs navigateur | Restrictions au besoin |
Ces en-têtes sont applicatifs (gérés côté serveur ou via un middleware). Pour la génération de secrets en ligne de commande, voir CLI Security.
Helmet (Node.js / Express)
Helmet est le package standard pour définir les headers de sécurité dans une application Express.
npm install helmetconst express = require('express');
const helmet = require('helmet');
const app = express();
// Applique tous les headers recommandés par défaut
app.use(helmet());
// Configuration personnalisée — activer les headers un par un
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "'unsafe-inline'"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:", "https:"],
}
},
xFrameOptions: { action: 'deny' },
hsts: {
maxAge: 31536000,
includeSubDomains: true,
preload: true
}
}));CORS — Contrôle d’accès inter-origines
Configurez CORS uniquement pour les origines connues. Ne jamais utiliser Access-Control-Allow-Origin: * en production.
const cors = require('cors');
app.use(cors({
origin: ['https://mon-domaine.com', 'https://app.mon-domaine.com'],
methods: ['GET', 'POST'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true
}));En-tête manuel (sans middleware)
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', 'https://mon-domaine.com');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
res.setHeader('Access-Control-Allow-Credentials', 'true');
next();
});Content-Security-Policy (CSP)
La CSP est l’en-tête le plus puissant contre les XSS. Elle doit être progressive : commencer large, puis resserrer.
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src 'self' https://api.example.com; frame-ancestors 'none'Directives essentielles
| Directive | Usage |
|---|---|
default-src | Politique par défaut (applique si aucune directive spécifique ne correspond) |
script-src | Sources autorisées pour les scripts |
style-src | Sources autorisées pour les feuilles de style |
img-src | Sources autorisées pour les images |
connect-src | Sources autorisées pour XHR, fetch, WebSocket |
frame-ancestors | Origines autorisées à intégrer la page via iframe |
report-uri | Endpoint de rapport des violations |
Ne jamais utiliser 'unsafe-inline' pour script-src en production si possible. Cela annule la protection CSP contre les XSS par injection de scripts.
X-Frame-Options
Empêche le clickjacking en interdisant l’intégration de la page dans un iframe depuis un autre domaine.
// Via Helmet
app.use(helmet({ xFrameOptions: { action: 'deny' } }));
// Manuel
res.setHeader('X-Frame-Options', 'DENY');| Valeur | Comportement |
|---|---|
DENY | Aucune iframe, même sur le même domaine |
SAMEORIGIN | iframe autorisé uniquement depuis le même domaine |
ALLOW-FROM uri | Déprécié, à remplacer par Permissions-Policy |
X-Content-Type-Options
Empêche le navigateur d’interpréter un fichier comme un type de contenu différent de celui annoncé.
res.setHeader('X-Content-Type-Options', 'nosniff');Sans cet en-tête, un navigateur peut exécuter un fichier .js servi avec le Content-Type: text/plain, ou inversément.
Cookies sécurisés
Les cookies contiennent souvent des tokens de session. Ils doivent être protégés au niveau des attributs.
res.cookie('session', token, {
httpOnly: true, // inaccessible au JavaScript côté client
secure: true, // envoyé uniquement via HTTPS
sameSite: 'strict', // empêche l'envoi lors de requêtes cross-site
maxAge: 3600000 // expiration en millisecondes
});| Attribut | Protection |
|---|---|
HttpOnly | Le cookie n’est pas lisible via document.cookie |
Secure | Le cookie n’est envoyé que sur les connexions HTTPS |
SameSite=Strict | Le cookie n’est jamais envoyé lors d’une requête cross-site |
SameSite=Lax | Envoyé uniquement lors d’une navigation globale (GET, lien) |
Referrer-Policy
Contrôle quelles informations d’URL sont transmises dans l’en-tête Referer.
res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');| Politique | Comportement |
|---|---|
no-referrer | Aucun en-tête Referer |
origin | Seule l’origine est transmise |
strict-origin-when-cross-origin | URL complète sur même origine, uniquement l’origine sur cross-origin |
no-referrer-when-downgrade | URLs complètes, sauf si HTTPS → HTTP |
Permissions-Policy
Contrôle quelles fonctionnalités du navigateur une page peut utiliser.
res.setHeader('Permissions-Policy', 'geolocation=(), microphone=(), camera=()');Vérification en production
# Vérifier les headers retournés par un serveur
curl -I https://mon-domaine.com
# Sortie attendue (extraits) :
# Content-Security-Policy: ...
# X-Frame-Options: DENY
# X-Content-Type-Options: nosniff
# Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
# Referrer-Policy: strict-origin-when-cross-originChecklist de déploiement
- Helmet ou middleware équivalent installé et activé
- CORS configuré avec origines explicites (pas de
*en production) - CSP définie et testée (utiliser
report-uripour détecter les violations avant de passer en mode bloqueur) -
X-Frame-Options: DENYouSAMEORIGINappliqué -
X-Content-Type-Options: nosniffactivé - Cookies avec
HttpOnly,Secure,SameSite -
Referrer-Policydéfini - HTTPS forcé (redirection HTTP → HTTPS)
-
Strict-Transport-Securityavecpreloadactivé