Aller au contenu principal
~$ guillaume.putier.fr

notes/en-tetes-nginx-perdus

nginx efface tes en-têtes de sécurité sans rien dire

Une location qui pose son propre add_header fait disparaître tous ceux du bloc server, et rien ne te prévient.

  • nginx
  • sécurité
  • http

Tu as posé X-Frame-Options, nosniff, Referrer-Policy, Permissions-Policy et une CSP au niveau server. nginx -t te dit que la conf est bonne. Tu lances curl -sI sur la page d'accueil pour te faire plaisir, et il n'y a rien. Pas un en-tête de sécurité. Tu essaies une feuille de style sous /_astro/, rien non plus. Seul robots.txt les porte encore.

C'est exactement ce que servait ce site le 13 septembre 2026, en production.

La règle nginx est courte : un bloc hérite des add_header de son parent seulement s'il n'en déclare aucun lui-même. La conf avait deux location pour le cache, une sur \.html$ et une sur les assets, chacune avec son add_header Cache-Control. Ça suffit. Les cinq en-têtes du server disparaissent pour toute réponse qui tombe dans ces locations. Et la page d'accueil passe par index, donc par \.html$. Le trou touche la page la plus vue du site.

Aucun avertissement au nginx -t, rien dans les journaux. Le HSTS que je voyais encore dans la réponse venait du proxy TLS en amont, pas du conteneur : il masquait le reste.

Le correctif tient en une règle d'hygiène. Tous les add_header remontent au niveau server, et la valeur de Cache-Control se calcule ailleurs, avec un map $uri $cache_control posé en tête du fichier dans le contexte http, puis un seul add_header Cache-Control $cache_control always;. Plus aucune location ne déclare d'en-tête, donc plus rien à effacer. nginx 1.29.3 apporte add_header_inherit merge; qui tue le piège à la racine, mais la branche stable 1.28 ne l'a pas.

Ce qu'il faut contrôler : pas la configuration, la réponse. Relire le fichier ne prouve rien, tu viens de voir pourquoi. Le dépôt de ce site porte scripts/check-headers.sh, lancé en CI contre l'image avant qu'elle parte. Il vérifie le code de retour et les en-têtes sur /, sur une feuille de style sous /_astro/, sur une image, sur robots.txt et sur une URL absente. Contre-épreuve du même jour : passé sur la production d'avant correctif, il a échoué sur 27 contrôles.

Le jour où quelqu'un rajoute une location avec son propre en-tête, le piège se réarme tout seul. D'où le script.

retour aux notes