← Tous les articles

Sécuriser un site statique : CSP, en-têtes et .htaccess

On entend souvent qu'un site statique « n'a rien à pirater » : pas de base de données, pas de back-office, pas de mot de passe à voler. C'est en partie vrai — et c'est précisément pour ça qu'on néglige sa sécurité. Pourtant, un site statique garde une vraie surface d'attaque : injection de contenu, clickjacking, fuite de fichiers sensibles, dépendances tierces qui pistent vos visiteurs. Voici les réglages concrets que j'applique systématiquement, et que j'ai posés sur ce site même.

Une CSP stricte, le réflexe n°1

La Content Security Policy est la mesure qui a le plus d'impact. Elle dit au navigateur ce qu'il a le droit de charger — et bloque tout le reste. Je pars d'une base qui interdit tout, puis j'autorise uniquement le strict nécessaire.

Header set Content-Security-Policy "default-src 'none'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; base-uri 'self'; frame-ancestors 'none'; object-src 'none'; upgrade-insecure-requests"

default-src 'none' ferme la porte par défaut. Ensuite, script-src 'self' n'autorise que mes propres scripts (donc aucun script inline injecté ne s'exécute), frame-ancestors 'none' empêche qu'on encapsule le site dans une iframe, et object-src 'none' neutralise les plugins. Si une faille de contenu se glissait quelque part, le navigateur refuserait quand même d'exécuter le code étranger.

Les en-têtes qui ferment les portes

Quelques en-têtes supplémentaires éliminent des classes entières d'attaques, pour quelques lignes :

  • HSTS force le HTTPS sur toutes les visites suivantes.
  • X-Frame-Options: DENY bloque le clickjacking.
  • X-Content-Type-Options: nosniff empêche le navigateur de « deviner » un type de fichier.
  • Referrer-Policy limite ce qu'on transmet aux sites externes.
  • Permissions-Policy désactive caméra, micro, géolocalisation… dont le site n'a pas besoin.

Aucun n'a de coût visible pour le visiteur, et ensemble ils referment l'essentiel des vecteurs classiques.

Ne rien exposer par accident

La fuite la plus fréquente sur un site statique, c'est un fichier qui traîne : une sauvegarde .bak, un .git, un fichier de config. Deux règles règlent le problème — bloquer les fichiers cachés et les extensions sensibles, et couper le listing de répertoire :

Options -Indexes
<FilesMatch "^\.">
  Require all denied
</FilesMatch>
<FilesMatch "\.(bak|old|sql|env|log|ini|yml|map)$">
  Require all denied
</FilesMatch>

J'ajoute une page d'erreur propre avec ErrorDocument 404 /404.html : l'utilisateur reste sur le site, et on ne dévoile pas la configuration du serveur.

Moins de tiers = moins de risques

Chaque ressource externe est une dépendance que vous ne contrôlez pas — et souvent un traceur. Sur ce site, j'héberge les polices localement plutôt que de les charger depuis un CDN : plus aucune donnée (pas même l'adresse IP du visiteur) n'est transmise à un tiers, la CSP peut rester verrouillée sur 'self', et la page charge plus vite. Pas de cookie, pas d'analytics, pas de script publicitaire : moins de surface, moins de conformité à gérer, et un meilleur respect de la vie privée.

En résumé

Sécuriser un site statique prend environ une heure, ne coûte rien en performance, et se vérifie en quelques secondes sur un outil comme securityheaders.com ou l'observatoire de Mozilla. C'est exactement le genre de finition que je mets sur chaque projet : ce n'est pas spectaculaire, mais c'est ce qui sépare un site « qui marche » d'un site livré proprement.

Un projet en tête ? Parlons-en.

Me contacter