Assurer la sécurité d’une application web ne se limite plus au chiffrement (HTTPS/TLS) ou à la simple validation des entrées côté serveur. Le véritable défi pour le développeur est de configurer une défense en profondeur directement au niveau de la couche transport et du navigateur.
Les Headers HTTP de sécurité sont votre première ligne de défense contre les attaques côté client.
👉 Ajoute ce bloc :
Petit rappel : HSTS (HTTP Strict-Transport-Security) force le navigateur à n’utiliser que HTTPS pour un domaine donné, même si l’utilisateur tape une URL en HTTP. C’est un socle indispensable… mais insuffisant. Une fois le transport verrouillé, il reste à contrôler ce que le navigateur a le droit de charger et d’exécuter. C’est là qu’interviennent les headers de “défense en profondeur”.
Nous allons décortiquer trois briques clés de cette sécurité post-HSTS : Content-Security-Policy (CSP), Permissions-Policy, et Expect-CT – ce dernier étant aujourd’hui un mécanisme en fin de vie, mais essentiel pour comprendre l’évolution de la chaîne de confiance TLS.
1. Le Pilier Fondamental : Content-Security-Policy (CSP)
Le CSP est le pare-feu le plus puissant côté client. Son rôle est de dicter au navigateur quelles sources de contenu sont fiables (scripts, styles, images) et de bloquer toutes les autres. Il neutralise la majorité des attaques de type Cross-Site Scripting (XSS) et des injections de données.
Le Passage à la Modernité (Adieu aux unsafe-*)
Déclarer un CSP est trivial ; déclarer un CSP réellement sécurisé l’est beaucoup moins. L’erreur la plus fréquente est de recourir à des directives laxistes comme unsafe-inline (autorise tous les scripts dans les balises <script>) ou unsafe-eval (autorise eval()).
La Solution Sûre : Les Nonces et les Hashes
Pour autoriser un code inline spécifique sans autoriser tout l’inline, vous devez utiliser :
- Le Nonce (
'nonce-random_base64_string') : Vous générez une chaîne aléatoire unique pour chaque requête HTTP, l’incluez dans le Header CSP (ex:script-src 'nonce-abc123';), et ajoutez cet attribut (nonce="abc123") uniquement aux balises<script>fiables. - Les Hashes (
'sha256-hash_du_script') : Vous calculez le hash (SHA-256 ou SHA-384) d’un script ou style inline, et l’ajoutez directement au Header.
Le Mémorandum du Dev avisé : Une fois le CSP activé, si le navigateur détecte un script non autorisé, il le bloque purement et simplement, même si un attaquant a réussi à l’injecter dans le DOM.
Surveillance : Content-Security-Policy-Report-Only
Pour éviter de casser votre application lors du déploiement d’un nouveau CSP, commencez toujours par le mode Report-Only.
Content-Security-Policy: default-src 'self';
script-src 'self' 'nonce-{{nonce}}' https://cdn.example.com;
style-src 'self' 'sha256-...hash_css...' https://fonts.googleapis.com;
img-src 'self' https://images.example.com data:;
object-src 'none';
base-uri 'self';
frame-ancestors 'self';
Ce mode n’applique pas les règles, mais signale toutes les violations à l’URL spécifiée (/csp-violation-reporter), permettant de tester la politique en production.
À noter :
report-uriest progressivement remplacé parreport-todans les spécifications modernes, mais reste massivement supporté. L’important est surtout d’avoir un point de collecte exploitable, même si, au début, vous ne faites que loguer ces rapports.
Le Garde du Corps du CSP : X-Frame-Options et frame-ancestors
Le Clickjacking (ou UI Redressing) est une attaque qui consiste à rendre un site invisible ou transparent et à le superposer à un autre site, incitant l’utilisateur à cliquer sur un élément dangereux sans le savoir.
| Header | Rôle | Conséquence |
X-Frame-Options: DENY | Le plus strict. Interdit l’inclusion de la page dans toute <frame>, <iframe> ou <object>. | Recommandé si votre site ne doit jamais être intégré. |
X-Frame-Options: SAMEORIGIN | Autorise l’inclusion uniquement si l’origine du site parent (qui inclut la frame) est la même. | Bonne option par défaut. |
Remplacement Moderne : CSP frame-ancestors | Bien que X-Frame-Options fonctionne encore, la directive frame-ancestors de CSP est la solution moderne et plus flexible. | Permet de spécifier des domaines autorisés (ex : frame-ancestors 'self' *.partenaire.com;). |
# Ancienne approche
X-Frame-Options: SAMEORIGIN
# Approche moderne recommandée
Content-Security-Policy: frame-ancestors 'self' https://partner.example.com;
Le Contrôle des Capacités : Permissions-Policy (anciennement Feature-Policy)
Le header Permissions-Policy permet de restreindre l’accès du navigateur à des API puissantes et potentiellement intrusives (caméra, microphone, géolocalisation, plein écran, etc.), améliorant la performance et la vie privée.
Anciennement appelée Feature-Policy, cette directive a été renommée en Permissions-Policy pour refléter le fait qu’elle contrôle l’accès à des “permissions” puissantes du navigateur.
Ce contrôle est crucial, surtout si vous intégrez du contenu tiers via des iframes.
Permissions-Policy: geolocation=(self "https://maps.example.com"), camera=(), microphone=()
Trois patterns reviennent souvent :
–(): personne n’a le droit d’utiliser l’API (même pas votre domaine),
–(self): seule l’origine courante est autorisée,
–(* ): tout le monde peut l’utiliser (même les iframes tierces).
À partir de là, vous pouvez affiner finement, comme dans l’exemple ci-dessus avec un domaine tiers explicitement autorisé.
geolocation=(self "https://maps.example.com")
Autorise la géolocalisation pour votre propre domaine (self) et un domaine spécifique de confiance.
camera=(), microphone=()
Désactive complètement l’accès à la caméra et au microphone pour tous les contextes, y compris votre code et les iframes.
La Confiance dans le Chiffrement : Certificate Transparency (et le rôle historique d’Expect-CT)
Le Certificate Transparency (CT) est un mécanisme de sécurité qui exige que les autorités de certification (CA) publient tous les certificats SSL qu’elles émettent dans des journaux publics.
Historiquement, l’en-tête Expect-CT permettait de demander au navigateur de vérifier que le certificat utilisé pour votre site était bien enregistré dans ces journaux. Aujourd’hui, les principaux navigateurs ont intégré la vérification CT en natif et ont commencé à retirer le support d’Expect-CT.
Le concept reste important à comprendre, mais l’en-tête lui-même ne doit plus être considéré comme un pilier à déployer sur une nouvelle application.
Le header Expect-CT demande au navigateur de vérifier que le certificat SSL utilisé pour votre site est bien publié dans les journaux CT.
À titre historique, un header
Expect-CTtypique ressemblait à ceci :
Expect-CT: max-age=86400, enforce, report-uri "https://votre-reporting.com/ct"
max-age
Durée pendant laquelle le navigateur doit se souvenir de la règle (ici, 24 heures).
enforce
Indique au navigateur d’arrêter la connexion si le certificat n’est pas conforme aux journaux CT.
report-uri
URL vers laquelle les violations de CT doivent être envoyées (mode Report-Only avant enforce).
Dans une application moderne, vous n’avez plus besoin d’ajouter ce header : concentrez-vous plutôt sur un certificat correctement émis, surveillez vos certificats via votre fournisseur (ou des outils externes), et laissez le navigateur faire son travail de vérification CT.
Conclusion : La Sécurité est une Configuration Continue
Ces headers ne sont pas des options ; ils sont des exigences pour une architecture moderne et responsable. L’implémentation de CSP avec des Nonces ou des Hashes demande un effort d’ingénierie initial, mais il offre une protection inégalée contre les scripts injectés.
La sécurité n’est pas un produit, c’est un processus : la configuration des headers doit être révisée en permanence à mesure que les capacités des navigateurs et les menaces évoluent.
Checklist minimale à viser en production :
- HSTS activé avec un
max-agesuffisant etincludeSubDomainssi pertinent. - Un CSP strict basé sur des nonces/hashes, sans
unsafe-inlineniunsafe-eval. frame-ancestorscorrectement configuré (et éventuellementX-Frame-Optionspour compatibilité).- Un header
Permissions-Policyqui désactive par défaut les API sensibles (caméra, micro, géolocalisation…) et n’ouvre que ce qui est nécessaire. - Une revue régulière de ces headers à chaque évolution majeure de l’appli (nouveaux CDN, nouvelles iframes, nouvelles fonctionnalités).

