Aussi disponible en : English · Español · Português · العربية
Générateur et vérificateur de CSP
Rédigez une Content-Security-Policy, puis confrontez-lui une URL réelle — et voyez quelles expressions de votre politique ne servent strictement à rien.
Qu’est-ce qu’une Content Security Policy ?
Une Content Security Policy est un en-tête HTTP qui indique au navigateur d’où une page a le droit de charger des ressources. C’est une liste de directives — script-src, img-src, style-src et les autres — chacune suivie des sources qu’elle autorise. Si la page tente de charger quelque chose que la politique n’autorise pas, le navigateur refuse.
L’objectif est de limiter les dégâts. Si un attaquant parvient à injecter du balisage dans votre page, une bonne politique est ce qui empêche ce balisage de charger son script. La CSP ne remplace pas un échappement correct des sorties ; c’est la couche qui limite la gravité de la panne quand l’échappement échoue.
En écrire une est facile. Savoir ce que l’on a réellement écrit ne l’est pas, et c’est cet écart que cette page cherche à combler. Les règles de correspondance de CSP Level 3 sont plus surprenantes qu’il n’y paraît, et plusieurs d’entre elles font que des parties d’une politique sont ignorées en silence : une politique peut énumérer une douzaine d’hôtes autorisés qui n’ont aucun effet, sans que rien ne vous le signale.
Comment l’utiliser
- Partez d’un modèle ou collez votre propre politique. Le modèle strict repose sur un nonce et correspond aux recommandations actuelles ; le modèle typique ressemble davantage à ce que la plupart des sites déploient réellement. Modifiez le texte librement : tout ce qui suit se met à jour au fil de la frappe.
- Lisez ce que la politique fait réellement. Le panneau du dessous énumère les constats : expressions ignorées, directives manquantes, sources qui défont la protection que vous croyiez avoir. Chacun est une règle de la spécification et non une opinion.
- Confrontez-lui ensuite une URL réelle. Choisissez le type de ressource, collez l’URL à charger et l’origine depuis laquelle votre page est servie. Vous obtenez un verdict, la directive consultée après la chaîne de repli, et l’expression exacte qui a tranché.
Les règles de correspondance que presque personne ne connaît
La correspondance de schéma est asymétrique et procède à une élévation. La spécification indique que le schéma http correspond à https, si bien que script-src http://example.com autorise aussi https://example.com — mais pas l’inverse. Écrire la forme non sécurisée autorise silencieusement les deux. La même règle fait correspondre ws à wss, http et https à la fois, une permission bien plus large que ce que quiconque vise.
Un hôte à joker n’inclut pas le domaine lui-même. Le motif *.example.com est traité en retirant l’astérisque initial et en exigeant que l’hôte se termine par .example.com, or example.com ne s’y termine pas. Une politique autorisant *.example.com bloque donc example.com, soit l’inverse de ce que presque tout le monde croit avoir écrit. Cela implique aussi qu’aucun motif d’hôte ne correspond jamais à une adresse IP, l’algorithme exigeant un domaine.
Les chemins ne sont des correspondances par préfixe que s’ils se terminent par une barre oblique. Sans barre finale, la correspondance est exacte : script-src https://cdn.example/js n’autorise donc que cette URL précise et rien en dessous. Les segments sont en outre décodés des séquences pour cent avant comparaison, si bien qu’une barre encodée reste un seul segment et non deux.
Et les ports retombent sur leur valeur par défaut. Une source sans port correspond au port par défaut du schéma : https://example.com et https://example.com:443 sont donc une seule origine — ce que 'self' doit d’ailleurs signifier.
Les parties de votre politique qui ne servent à rien
Deux règles font que certaines expressions figurent dans une politique sans le moindre effet, et ni l’une ni l’autre ne se voit si l’on ne sait pas la chercher.
La première est 'strict-dynamic'. Lorsqu’elle apparaît dans script-src ou default-src, la spécification prévoit que les sources d’hôte et de schéma, ainsi que 'unsafe-inline' et 'self', sont ignorées au chargement des scripts. Seuls les nonces et les empreintes comptent encore. C’est délibéré et c’est ainsi que fonctionne l’approche moderne à nonce, mais cela signifie qu’une politique disant script-src 'strict-dynamic' 'nonce-abc' https://cdn.example 'self' n’autorise rien de ce CDN par son hôte. Le vérificateur énumère toutes les expressions qu’il a ignorées et indique quelle règle les a écartées.
La seconde est 'unsafe-inline' à côté d’un nonce ou d’une empreinte. Dans ce cas 'unsafe-inline' est ignoré, ce qui est précisément l’astuce permettant d’écrire une politique qui se dégrade proprement dans les vieux navigateurs : ceux qui comprennent les nonces obéissent au nonce, les autres se rabattent sur 'unsafe-inline'. Utile quand c’est voulu, inquiétant quand c’est accidentel : cette page distingue donc les deux cas au lieu de signaler 'unsafe-inline' de la même façon dans l’un et l’autre.
Il existe un troisième trou, d’absence plutôt que d’omission. Les directives frame-ancestors, form-action et base-uri ne se rabattent pas sur default-src. Une politique default-src 'self' ne restreint donc nullement l’encadrement, ne restreint pas la destination des formulaires, et laisse base-uri ouvert, si bien qu’un balisage injecté peut réorienter toutes les URL relatives de la page. Le vérificateur vous dira franchement qu’aucune directive ne s’applique.
Limites honnêtes
Cet outil vérifie la correspondance d’URL, la partie de CSP qui comporte de véritables règles et de véritables surprises. Il ne modélise pas tout ce que fait un navigateur. Le script et le style en ligne, eval, les redirections, l’héritage dans les workers, le bac à sable, les trusted types et l’envoi de rapports sortent de ce que le vérificateur traite, et une politique qui autorise ici une URL peut malgré tout bloquer la ressource dans un navigateur pour l’une de ces raisons.
Les nonces et les empreintes sont reconnus mais non évalués. Qu’un script en ligne donné corresponde à un nonce dépend du balisage et non de la politique : le vérificateur les traite donc comme des expressions existantes, sans prétendre qu’elles laissent passer telle ou telle URL.
Les constats sont des règles, pas une note de sécurité. Une politique peut réussir tous les contrôles présentés ici et rester faible, car CSP ne peut pas protéger une page dont la propre origine sert du script contrôlé par l’attaquant. Rien sur cette page ne remplace un encodage correct des sorties.
Il n’existe ni suite de conformité CSP ni comparateur de référence sur npm implémentant les algorithmes d’expressions de source : le moteur a donc été vérifié contre les exemples travaillés de la spécification elle-même et contre ses algorithmes transcrits en assertions, chacune portant son numéro de section. Chaque règle asymétrique est testée dans les deux sens, car une suite qui ne vérifie que le sens permissif est satisfaite par une implémentation trop laxiste — précisément la défaillance qui compte ici.
Pourquoi est-ce gratuit ?
Parce que cela ne coûte rien à faire tourner. La politique est analysée et l’URL vérifiée dans votre navigateur au fil de la frappe ; rien n’est envoyé, rien n’est journalisé, et aucun serveur ne voit la politique ni les URL que vous collez.
Ni compte, ni inscription, ni rien réservé. Les règles de correspondance proviennent de la spécification Content Security Policy Level 3 et non du résumé qu’en fait un autre site, et les contrôles qui les vérifient sont versionnés à côté de la page.