Aller au contenu
Tous les articles
Tutoriels· 3 min

Configurer les en-têtes de sécurité HTTP avec nginx

CSP, HSTS, X-Frame-Options… Les en-têtes HTTP indispensables, comment les déclarer proprement dans nginx et le piège de l'héritage de add_header.

Par Équipe NETEDIS

Les en-têtes de sécurité HTTP sont l'une des protections les moins coûteuses à mettre en place : quelques lignes de configuration suffisent à bloquer des classes entières d'attaques côté navigateur (clickjacking, injection de scripts, interception sur HTTP). Ce tutoriel montre comment les déclarer dans nginx, et surtout comment éviter le piège qui fait silencieusement disparaître la moitié d'entre eux.

Les en-têtes à connaître

En-tête Protège contre Valeur de départ raisonnable
Strict-Transport-Security Rétrogradation vers HTTP, interception max-age=31536000; includeSubDomains
Content-Security-Policy Injection de scripts (XSS), chargements non maîtrisés default-src 'self' puis à affiner
X-Frame-Options Clickjacking (site affiché dans une iframe) SAMEORIGIN
X-Content-Type-Options Interprétation d'un fichier avec un mauvais type nosniff
Referrer-Policy Fuite d'URL internes vers des sites tiers strict-origin-when-cross-origin
Permissions-Policy Accès abusif caméra, micro, géolocalisation… camera=(), microphone=(), geolocation=()

Le piège : add_header ne s'hérite pas toujours

Dans nginx, une directive add_header déclarée au niveau server est héritée par les blocs location… sauf si la location déclare elle-même au moins un add_header. Dans ce cas, tous les en-têtes du niveau supérieur sont ignorés pour cette location.

server {
    add_header X-Frame-Options "SAMEORIGIN" always;
 
    location /assets/ {
        # Cette ligne fait disparaître X-Frame-Options pour /assets/ !
        add_header Cache-Control "public, max-age=31536000" always;
    }
}

C'est l'erreur la plus fréquente : la configuration semble correcte, mais certaines URL sont servies sans protection.

La solution : un fichier inclus dans chaque location

Regroupez les en-têtes dans un fichier dédié, par exemple /etc/nginx/snippets/security-headers.conf :

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header Content-Security-Policy "default-src 'self'; img-src 'self' data:; object-src 'none'; frame-ancestors 'self'; base-uri 'self'" 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;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;

Puis incluez-le dans chaque location qui sert du contenu :

location / {
    include /etc/nginx/snippets/security-headers.conf;
    try_files $uri $uri.html $uri/index.html =404;
}
 
location /assets/ {
    include /etc/nginx/snippets/security-headers.conf;
    add_header Cache-Control "public, max-age=31536000, immutable" always;
}

Le paramètre always garantit que les en-têtes sont aussi envoyés sur les réponses d'erreur (404, 500…), qui sont souvent oubliées.

Vérifier le résultat

Testez plusieurs types d'URL, pas seulement la page d'accueil :

for path in / /assets/app.css /page-inexistante; do
  echo "== $path"
  curl -sI "https://votre-domaine.fr$path" | grep -iE 'strict-transport|content-security|x-frame|x-content-type|referrer|permissions'
done

Chaque URL doit afficher les six en-têtes. Si une seule en manque, cherchez un add_header isolé dans la location correspondante.

Points d'attention

Vous souhaitez un audit de la configuration de vos serveurs web ? Contactez-nous.

Besoin d'aller plus loin ?

Nos experts vous accompagnent pour mettre ces bonnes pratiques en place dans votre contexte.

Parlons de votre projet

À lire aussi