Imposer SRI sur chaque script avec Integrity-Policy
CentralCSP Team ·
Dernière mise à jour:
Subresource Integrity (SRI) protège un élément à la fois. Vous hashez un fichier, collez le digest dans l'attribut integrity de la balise, et le navigateur le vérifie. Le prochain script que quelqu'un ajoute sans hash n'est pas protégé, et rien ne vous le signale. Le header de réponse Integrity-Policy corrige ce problème de portée : il exige SRI sur chaque script avec un seul header, et signale ceux qui en manquent.
La version courte : envoyez Integrity-Policy: blocked-destinations=(script) et le navigateur bloque tout script qui se charge sans métadonnées d'intégrité valides. Ajoutez une directive endpoints=() et un header Reporting-Endpoints, et il signale chaque script bloqué sous forme de report integrity-violation. Une variante report-only vous laisse mesurer l'écart avant d'imposer. Cet article couvre la syntaxe, le câblage du reporting et la façon dont ce header fait passer SRI d'un opt-in balise par balise à une règle valable sur tout le site.
Disponibilité récente
L'application d'Integrity-Policy pour la destination script est arrivée récemment dans les versions actuelles de Chrome, Firefox et Safari, et Firefox prend désormais en charge la livraison vers un endpoint. C'est récent et ce n'est pas encore Baseline : vérifiez la couverture sur les navigateurs qui comptent pour vous, et voyez-le comme une couche d'application doublée d'un signal de reporting.
Ce que fait Integrity-Policy
SRI est un opt-in par élément. Rien n'empêche un développeur d'ajouter un nouveau <script src> sans attribut integrity, et cette seule balise sans hash suffit à ouvrir la brèche qu'un attaquant cherche. Integrity-Policy la referme en posant l'exigence une seule fois, au niveau du header de réponse, plutôt que sur chaque balise.
Vous nommez les destinations de ressources qui doivent être protégées par intégrité, et le navigateur exige alors une valeur integrity valide à chaque chargement de ce type. Un script qui n'en a pas est bloqué (ou signalé, en mode report-only). La référence complète est la page de la politique Integrity-Policy.
Comment le configurer
Le header minimal nomme la destination à protéger :
Integrity-Policy: blocked-destinations=(script)blocked-destinations est la directive requise. Aujourd'hui, la seule valeur exploitable est script ; la destination style est moins bien prise en charge. Avec ce header seul, tout script chargé sans attribut integrity correct est bloqué, sans report.
Pour obtenir des reports, ajoutez une directive endpoints=() et déclarez ce nom d'endpoint dans un header Reporting-Endpoints. Les deux headers vont dans des blocs séparés :
Reporting-Endpoints: integrity-endpoint="https://<Endpoint-ID>.report.centralcsp.com"Integrity-Policy: blocked-destinations=(script), endpoints=(integrity-endpoint)Un détail de câblage piège souvent : Integrity-Policy choisit son endpoint de reporting avec la directive endpoints=(), et non avec le paramètre report-to= qu'utilisent COOP, COEP et Permissions-Policy. Le nom à l'intérieur de endpoints=() doit correspondre à un nom déclaré dans Reporting-Endpoints.
Commencez en mode report-only
Activer le blocage avant de savoir quels scripts portent SRI cassera la page : chaque script légitime mais sans hash sera bloqué en même temps que les indésirables. Passez d'abord par la variante report-only. Elle signale chaque script dépourvu d'intégrité valide sans rien bloquer : vous avez la liste complète avant d'imposer.
Integrity-Policy-Report-Only: blocked-destinations=(script), endpoints=(integrity-endpoint)Laissez-la tourner jusqu'à ce que les reports cessent de faire remonter des scripts que vous n'avez pas encore hashés. Ajoutez ensuite l'attribut integrity (ou supprimez la dépendance) pour tout ce qui est sur la liste, et basculez le header en Integrity-Policy pour imposer.
À quoi ressemble un report de violation
Quand un script se charge sans intégrité valide, le navigateur émet un report integrity-violation vers votre endpoint. Il indique la page, le script bloqué et si la politique imposait ou se contentait de signaler.
{
"type": "integrity-violation",
"age": 5,
"url": "https://example.com/",
"user_agent": "Mozilla/5.0 ...",
"body": {
"documentURL": "https://example.com/",
"blockedURL": "https://example.com/example-framework.js",
"destination": "script",
"reportOnly": false
}
}Le champ reportOnly vous dit quel mode a produit le report : true pour le header report-only, false une fois que vous imposez. Le blockedURL est le script dépourvu de SRI valide : c'est la ligne sur laquelle agir.
Le cas de la supply-chain
C'est là que le header justifie sa place. Prenons un script d'analytics chargé depuis un CDN avec un hash integrity correct, puis un compte CDN compromis dont le fichier est remplacé par une version altérée. SRI intercepte ce cas-là : les octets ne correspondent plus au hash, et le script est bloqué.
Imaginons maintenant qu'un collègue ajoute un nouveau tag tiers et oublie l'attribut integrity. Le SRI par élément ne peut rien faire : il n'y a aucun hash à vérifier. Integrity-Policy, si : le script sans hash viole la politique, il est donc bloqué et signalé comme integrity-violation. Le même report se déclenche quand une ressource est demandée en mode no-cors, où le navigateur ne peut tout simplement pas lire les octets pour les vérifier. Ce sont exactement les failles de supply-chain que l'on veut connaître avant qu'elles ne s'exécutent.
Integrity-Policy assure la moitié application ; savoir ce qui tourne vraiment sur vos pages est l'autre moitié. CentralCSP construit un inventaire de scripts à partir des reports de hash CSP, pour que vous voyiez chaque script, et ceux qui n'ont pas d'intégrité, avant de basculer le header en imposition. Commencez gratuitement pour cartographier vos scripts côté client et collecter les reports integrity-violation au même endroit.
