Comment les mots-clés CSP report-sha révèlent chaque script chargé
CentralCSP Team ·
Dernière mise à jour:
Vous pouvez demander au navigateur de vous indiquer le hash cryptographique de chaque script qui se charge sur une page. Les mots-clés de la politique de sécurité du contenu (CSP) 'report-sha256', 'report-sha384' et 'report-sha512' font exactement cela : ajoutez-en un à une directive de script, pointez la politique vers un endpoint de reporting, et chaque chargement de script produit un rapport qui contient le digest du script. Aucun script n'est bloqué. Vous obtenez un enregistrement précis et continu de ce qui s'exécute côté client, ce qui est la matière première d'un inventaire de scripts.
C'est un ajout récent, mené par Chromium (Chrome et les autres navigateurs Chromium), avec des travaux WebKit en cours et pas encore de prise en charge Firefox. Il n'est pas documenté sur MDN à l'heure où nous écrivons, traitez-le donc comme une fonctionnalité émergente, pas comme une fonctionnalité multi-navigateurs stable.
Ce que font les mots-clés report-sha
Les mots-clés sont des valeurs de source que vous placez dans une directive de script telle que script-src ou script-src-elem, aux côtés des autres mots-clés CSP que vous utilisez déjà :
'report-sha256'rapporte chaque script avec un digest SHA-256'report-sha384'rapporte chaque script avec un digest SHA-384'report-sha512'rapporte chaque script avec un digest SHA-512
Ils n'autorisent ni ne bloquent rien. Un digest dans un rapport sert uniquement à observer ; il n'a rien à voir avec les sources de hash appliquées (la forme 'sha256-...') qui autorisent un script inline ou externe précis ; voir comment générer un hash CSP pour produire ces derniers. Quand l'un de ces mots-clés report-sha est présent et qu'une ressource de type script est récupérée, le navigateur calcule le digest de la réponse et envoie un rapport à l'endpoint de la politique.
Le but, c'est l'inventaire. D'ordinaire, une CSP vous dit ce qui a été bloqué. Ces mots-clés vous disent ce qui s'est chargé, avec un digest que vous pouvez rapprocher de fichiers connus, pour qu'un backend construise un inventaire de scripts ou une nomenclature logicielle (SBOM) et repère les changements de script.
Mettez-le en place
Le reporting passe par la directive report-to, qui nomme un groupe déclaré dans le header Reporting-Endpoints. L'ancienne directive report-uri n'est pas utilisée par cette fonctionnalité, et la différence entre report-uri et report-to explique pourquoi. Si vous n'avez pas encore branché le reporting, suivez d'abord comment configurer le Reporting API du navigateur.
Voici la configuration minimale qui fonctionne. Déclarez un groupe d'endpoint, puis ajoutez le mot-clé et pointez la politique vers le groupe :
Reporting-Endpoints: hashes-endpoint="https://<Endpoint-ID>.report.centralcsp.com"Content-Security-Policy: script-src 'self' 'report-sha256';
report-to hashes-endpointL'endpoint doit être en HTTPS. Comme pour tout endpoint du Reporting API, une URL non sécurisée est ignorée.
Pour collecter les digests sans aucun risque de casser la page, démarrez en mode report-only avec le header Content-Security-Policy-Report-Only. Vous rassemblez d'abord le véritable inventaire de scripts, puis vous resserrez la politique appliquée une fois que vous savez ce qui se charge. On retrouve la même approche par étapes dans comment construire une CSP solide et démarrer avec le reporting CSP.
À quoi ressemble le rapport
Les rapports arrivent dans l'enveloppe standard du Reporting API : un tableau JSON envoyé avec Content-Type: application/reports+json. Le type de rapport externe pour cette fonctionnalité est "csp-hash".
Le corps du rapport porte l'identité et le digest du script. D'après la spec CSP Level 3, il contient ces champs :
{
"documentURL": "https://mywebsite.com/",
"subresourceURL": "https://mywebsite.com/my_script.js",
"hash": "sha256-r2hRGID3tnFVlAI+bMCPMjaKx/ovuqgaMic09dPqVCw=",
"destination": "script",
"type": "subresource"
}Deux champs type cohabitent à des niveaux différents, ne les confondez pas. Le type de rapport externe du Reporting API vaut "csp-hash". Le corps interne a son propre type, que l'exemple de la spec fixe à "subresource". Le champ hash est formaté comme <algorithm>-<base64>, la même forme que vous utiliseriez comme source de hash dans une politique.
Chromium émet le corps en camelCase, exactement comme ci-dessus (documentURL, subresourceURL, hash, type, destination), à l'intérieur de l'enveloppe standard du Reporting API, qui y ajoute type, url, user_agent et age. L'exemple de la spec CSP Level 3 sérialise le corps en snake_case (document_url, subresource_url), mais la forme livrée par Chromium est en camelCase.
Comportement et pièges
Quelques points à connaître avant de vous y fier.
- Endpoint uniquement, pas in-page. Les rapports
csp-hashne parviennent pas à unReportingObserverdans la page ; ils partent uniquement vers votre endpoint serveur. Cela diffère des rapports de violation CSP classiques, que Chromium achemine bien vers unReportingObserver. - Comportement en report-only. Les mots-clés report-sha collectent les hashs pour le reporting, que la politique environnante soit appliquée ou en report-only, car l'algorithme ne dépend pas de l'application.
- Les scripts cross-origin nécessitent CORS. Pour un script chargé depuis une autre origine, le navigateur ne peut calculer et inclure le digest que si la requête a été faite en mode CORS. Ajoutez
crossorigin="anonymous"à la balise pour que le navigateur puisse lire le corps de la réponse. Sans cela, le hash de ce script externe peut manquer.
<script
src="https://cdn.example.com/app.js"
crossorigin="anonymous"></script>- Combiner les algorithmes. La spec ne précise ni si les trois mots-clés peuvent être définis en même temps pour obtenir plusieurs digests par script, ni comment un mot-clé report-sha se comporte face à une source de hash appliquée dans la même directive. Testez-le dans votre propre configuration avant de vous y fier.
Ne confondez pas ces mots-clés de reporting avec les mots-clés d'application distincts 'url-sha256-...' et 'eval-sha256-...'. Ces derniers autorisent ou bloquent des scripts par digest d'URL ou d'eval. Les mots-clés report-sha ne font que rapporter.
Pourquoi cela compte pour un inventaire de scripts
Une fois que le navigateur rapporte un digest pour chaque script qui se charge, un backend peut faire le travail que de simples décomptes de violations n'ont jamais pu faire : lister chaque script qui s'est exécuté, rapprocher les digests et les URL de fichiers et versions connus, et signaler un changement dès qu'un digest jamais vu apparaît.
C'est la base de l'inventaire de scripts de CentralCSP. Nous ingérons ces rapports csp-hash, construisons l'inventaire de ce qui s'exécute sur chaque page, confrontons chaque version de bibliothèque aux CVE connues, et alertons quand un script ou un hash inattendu apparaît. Pour les pages de paiement, cette même visibilité sur les changements de scripts correspond directement aux exigences 6.4.3 et 11.6.1 de PCI DSS v4, où la plateforme vous aide à respecter les contrôles de gestion des scripts et de détection d'altération côté client (c'est votre QSA qui valide, pas nous).
Si vous voulez que les digests soient collectés et transformés en inventaire sans monter votre propre pipeline, démarrez gratuitement et pointez votre header Reporting-Endpoints vers votre endpoint CentralCSP.

Récapitulatif rapide
Ajoutez un mot-clé report-sha à une directive de script, déclarez un groupe Reporting-Endpoints, et référencez-le avec report-to. Le navigateur envoie un rapport csp-hash transportant le digest de chaque script, rien n'est bloqué, et vous obtenez la visibilité par script qui alimente un inventaire de scripts. Aujourd'hui, c'est du Chromium avant tout ; prévoyez donc une couverture partielle des navigateurs et rassemblez les digests en mode report-only avant de vous appuyer dessus.