Content Security Policy : limiter l’impact d’une XSS
Apprenez comment CSP indique au navigateur quels scripts et ressources il peut charger ou exécuter, et pourquoi cette défense complète la validation des données sans la remplacer.
Où en êtes-vous avec cette notion ?
Une indication personnelle, enregistrée uniquement dans ce navigateur.
À lire ensuite
Le format café
L’essentiel à comprendre, le temps d’un café.
Envie de creuser ? Un cours plus complet vous attend juste après, à déplier sans quitter cette page.
L’idée intuitive
Une faille XSS permet à du contenu injecté de devenir du JavaScript exécuté dans la page. La première défense reste d’éviter cette injection : encoder les sorties, valider les données et ne pas interpréter du HTML arbitraire.
Content Security Policy (CSP) ajoute une seconde barrière. Le serveur envoie une politique au navigateur pour lui dire quelles sources de scripts, styles, images ou connexions sont autorisées.
Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'
Cette ligne se lit comme une liste de permissions. Par défaut, les ressources doivent venir de la même origine. Les scripts suivent leur propre règle. Les anciens contenus de type plugin sont interdits et la base utilisée pour résoudre les URL relatives reste limitée au site.
Une liste blanche n’est pas toujours suffisante
Autoriser un domaine entier de scripts peut rester trop large. Une approche plus stricte consiste à autoriser explicitement chaque script produit par votre application avec un nonce ou un hash.
Content-Security-Policy: script-src 'nonce-a8F3kP2m'; object-src 'none'; base-uri 'none'
<script nonce="a8F3kP2m" src="/app.js"></script>
Le navigateur exécute ce script parce que son nonce correspond à celui annoncé dans l’en-tête. En production, ce nonce doit être imprévisible et généré à nouveau pour chaque réponse ; une valeur écrite en dur comme dans l’exemple annulerait une grande partie de l’intérêt du mécanisme.
Tester avant de bloquer
Une CSP trop stricte peut casser votre propre application. Pour observer les violations sans les bloquer immédiatement, utilisez d’abord l’en-tête de test :
Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self'
Le navigateur surveille alors la politique mais continue à charger les ressources. Vous pouvez corriger les dépendances oubliées avant de passer à l’en-tête réellement appliqué.
CSP ne remplace pas la sécurité applicative
CSP est une défense en profondeur. Elle ne nettoie pas une entrée utilisateur, ne vérifie pas les permissions métier et n’empêche pas votre serveur d’accepter une requête dangereuse. Elle réduit surtout ce qu’un navigateur acceptera d’exécuter ou de charger si une injection réussit malgré les autres protections.
Fiche mémo
Content-Security-Policyapplique réellement la politique.Content-Security-Policy-Report-Onlypermet de la tester sans blocage.default-srcfournit une règle de repli aux directives de chargement.- Une CSP stricte préfère des nonces ou des hashes aux grandes listes de domaines.
- Évitez de résoudre les erreurs en ajoutant machinalement
'unsafe-inline'aux scripts.
L’idée à emporter : CSP ne rend pas une XSS impossible ; elle réduit fortement ce que le navigateur acceptera d’exécuter lorsque votre première ligne de défense a échoué.
Et si on allait plus loin ?
Le café vous a donné les repères. Prenez maintenant le temps de comprendre les mécanismes et de pratiquer, si vous le souhaitez.
Aller plus loinConstruire une CSP stricte sans casser son applicationDévelopper le coursReplier le cours
Ce que vous saurez faire
Raisonner sur les principales directives, comprendre pourquoi les politiques basées sur nonce sont plus robustes que de larges allowlists, puis déployer une politique progressivement avec des rapports de violation.
1. Partir d’un défaut restrictif
Une politique devient plus simple à raisonner quand ce qui n’est pas explicitement autorisé est refusé. default-src joue ce rôle de repli pour plusieurs familles de ressources.
Content-Security-Policy:
default-src 'self';
script-src 'self';
img-src 'self' https: data:;
connect-src 'self' https://api.example.com;
object-src 'none';
base-uri 'none';
frame-ancestors 'none';
form-action 'self'
Les directives répondent à des questions différentes. script-src contrôle les scripts. connect-src concerne notamment fetch, WebSocket et EventSource. img-src contrôle les images. form-action limite les destinations de formulaires. frame-ancestors décide quels sites peuvent intégrer la page dans une frame et contribue ainsi à la protection contre le clickjacking.
La valeur 'self' désigne la même origine que le document. 'none' n’autorise aucune source pour la directive concernée.
Référence : W3C — Content Security Policy Level 3.
2. Pourquoi un nonce est plus précis qu’un domaine
Une allowlist comme script-src 'self' https://cdn.example.com fait confiance à toutes les ressources qui correspondent à ces sources. Sur une grande application, cette surface peut devenir difficile à maîtriser.
Une CSP stricte donne plutôt une autorisation cryptographique au script attendu pour cette réponse :
Content-Security-Policy: script-src 'nonce-r4Nd0mV4lu3'; object-src 'none'; base-uri 'none'
<script nonce="r4Nd0mV4lu3" src="/assets/app.js"></script>
Le serveur doit générer une valeur imprévisible pour chaque réponse, placer exactement la même valeur dans l’en-tête et dans les éléments script autorisés, puis ne jamais exposer ce nonce à du contenu non fiable. Réutiliser un nonce statique transforme le secret temporaire en simple mot de passe public.
Un hash fournit une autre stratégie pour un script inline dont le contenu est réellement stable : la politique autorise alors l’empreinte exacte du code. Dès que le script change, son hash doit changer lui aussi.
Référence : MDN — Content Security Policy.
3. Déployer avec Report-Only
Passer brutalement d’aucune politique à une CSP stricte peut bloquer une analytics, une police, une image distante ou un appel API légitime. Le mode report-only sert précisément à observer ces écarts avant l’activation.
Content-Security-Policy-Report-Only: default-src 'self'; script-src 'nonce-r4Nd0mV4lu3'; report-to csp-endpoint
La spécification CSP Level 3 décrit Content-Security-Policy-Report-Only comme un moyen d’expérimenter et de surveiller une politique sans l’appliquer. Les navigateurs peuvent ensuite envoyer les violations vers un mécanisme de reporting configuré par le site.
Une démarche saine est progressive : observer, nettoyer les faux positifs, activer la politique, puis continuer à surveiller les violations après chaque évolution de l’application.
4. Le raccourci dangereux : unsafe-inline
Une application ancienne contient souvent des scripts inline ou des attributs comme onclick. Face aux premiers blocages, ajouter 'unsafe-inline' semble pratique. Pour script-src, cela réautorise précisément une grande classe d’exécution inline que CSP cherchait à restreindre.
Préférez déplacer les comportements dans des scripts autorisés et utiliser des nonces ou hashes lorsque du code inline reste nécessaire. Le but n’est pas de faire disparaître les erreurs de console, mais de conserver une frontière de confiance réellement utile.
5. Une défense qui reste complémentaire
Même une CSP excellente ne remplace pas l’encodage des sorties, la validation des données, l’usage prudent du DOM, l’authentification et l’autorisation. La spécification W3C présente explicitement CSP comme une défense en profondeur contre l’injection de contenu, pas comme une première ligne de défense.
C’est une distinction importante : une politique navigateur limite les capacités du contenu injecté ; elle ne corrige pas la vulnérabilité qui a permis cette injection.
Pièges importants
- Ne copiez pas une CSP générique sans inventorier les ressources réellement nécessaires à votre application.
- Ne réutilisez jamais un nonce statique entre les réponses.
- N’élargissez pas
script-srcavec'unsafe-inline'uniquement pour supprimer un message d’erreur. - Testez d’abord une politique restrictive en report-only, mais ne laissez pas éternellement la protection au seul stade du rapport.
- Gardez la politique près de votre architecture réelle : chaque nouveau CDN, endpoint API ou intégration tierce doit justifier l’autorisation qu’il reçoit.
Mémo final
Une bonne CSP part du principe que le navigateur ne doit exécuter que ce que vous pouvez identifier comme intentionnel. Les nonces et hashes réduisent la confiance accordée à de larges origines, tandis que le mode report-only permet d’atteindre cette rigueur progressivement sans transformer la sécurité en panne de production.
Vous pouvez aussi vous arrêter ici. L’approfondissement est facultatif.
Les repères Cours Café
Pour aller à la source
Documentation de référence. Vérification éditoriale encore à effectuer.
Gardez une trace de cette idée.
Favoris, notes et progression seront disponibles après connexion du stockage distant.