Subresource Integrity
Avec SRI, le navigateur hache un script ou une feuille de style téléchargée et la refuse si le hash ne correspond pas, contre un CDN compromis.
Dernière mise à jour:
Subresource Integrity (SRI) est l'attribut integrity que vous ajoutez à un
<script> ou à un <link rel="stylesheet"> qui charge du code depuis un autre hôte.
Le navigateur hache les octets qu'il télécharge et les compare au hash que vous avez
écrit. S'ils ne correspondent pas, le navigateur refuse d'exécuter ou d'appliquer la
ressource et la traite comme une erreur réseau. SRI défend contre une menace
précise : un hôte tiers ou un réseau de diffusion de contenu (CDN) qui vous sert du
code altéré ou compromis.
Une directive est morte, une autre est la voie moderne
L'ancienne directive CSP require-sri-for n'a jamais été livrée dans un navigateur stable et est abandonnée. Ne l'utilisez pas. Pour exiger SRI aujourd'hui, vous utilisez le header Integrity-Policy, qui est récent et pas encore Baseline. Voir Prise en charge par les navigateurs.
Un exemple minimal
Vous ajoutez le hash, l'hôte de la ressource, et (pour un hôte cross-origin)
l'attribut crossorigin. Le navigateur fait le reste.
<script
src="https://cdn.example.com/library.js"
integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
crossorigin="anonymous"
></script>Si le fichier à cette URL change ne serait-ce que d'un octet, le hash ne correspond plus et le navigateur écarte le script. C'est tout l'intérêt : vous épinglez une version exacte, connue et saine.
Syntaxe et algorithmes
Une valeur d'intégrité est un préfixe d'algorithme, un tiret, et un digest encodé en base64 des octets de la réponse.
<link
rel="stylesheet"
href="https://cdn.example.com/app.css"
integrity="sha384-VuArbKap7CY5uykM6oqf+R9GqQ8Kux9rx7HNQlGYl1kPzQho1wx4JwY8wCdgcRRap"
crossorigin="anonymous"
/>Trois fonctions de hachage sont admises : sha256, sha384 et sha512. Vous pouvez
lister plusieurs tokens séparés par des espaces, et le traitement du navigateur
dépend du fait que les algorithmes diffèrent ou non :
- Algorithmes différents (le plus fort gagne). Si vous listez un token
sha256et un tokensha512, le navigateur choisit l'algorithme le plus fort présent et ne valide que contre celui-là. Lister un hash plus faible à côté d'un plus fort n'affaiblit pas la vérification. - Même algorithme (une correspondance suffit). Si vous listez deux tokens
sha384, la ressource est acceptée quand elle correspond à l'un ou l'autre. C'est ainsi que vous admettez plus d'un contenu acceptable, par exemple pendant une bascule entre deux versions de fichier.
Le digest est le hash du corps brut de la réponse, encodé en base64, pas un hash de l'URL ni du nom de fichier.
Comment générer le hash
La valeur d'intégrité est le digest encodé en base64 des octets bruts de la réponse,
préfixé par l'algorithme (sha384-). Générez-la avec notre
générateur SRI, qui produit la valeur integrity complète à
partir d'une URL ou d'un fichier et renvoie les variantes sha256, sha384 et
sha512 à coller dans l'attribut.
L'exigence crossorigin
SRI repose sur le Cross-Origin Resource Sharing (CORS). Le navigateur ne peut pas lire les octets d'une réponse cross-origin opaque, donc il ne peut pas vérifier un hash contre eux.
Pour une ressource cross-origin, l'attribut integrity ne fait rien à lui seul.
Vous devez aussi définir crossorigin="anonymous" (ou use-credentials), et l'hôte
qui sert la ressource doit renvoyer un header Access-Control-Allow-Origin qui
autorise votre origine. Manquez l'une des deux pièces et la ressource échoue toujours
à se charger.
Access-Control-Allow-Origin: *Pour une ressource same-origin, le navigateur peut déjà lire les octets, donc
aucun attribut crossorigin n'est nécessaire.
Ce que SRI couvre et ce qui reste hors champ
SRI s'applique à un ensemble fixe de types de ressources :
- Les éléments
<script>. <link rel="stylesheet">.<link rel="preload">et<link rel="modulepreload">.- Le paramètre
integritydu header HTTPLink, l'équivalent par header d'un preload. - Les modules ES importés dynamiquement, via le champ
integrityd'une import map, pris en charge par les versions actuelles de Chrome, Firefox et Safari.
Il ne couvre pas les images, l'audio, la vidéo, <iframe> ni <object>
aujourd'hui.
Le coût, c'est la maintenance. SRI a besoin d'un fichier épinglé et immuable. Une ressource qui mute, un CDN qui minifie automatiquement, ou une URL qui pointe toujours vers le "dernier" build, casse le hash à chaque changement. Vous devez régénérer le hash chaque fois que le fichier change légitimement, ce qui explique que les équipes épinglent une URL versionnée et mettent à jour URL et hash ensemble. L'inventaire de scripts de CentralCSP détecte les scripts tiers présents sur vos pages et signale quand l'un d'eux change, le signal qu'un hash SRI doit être mis à jour ou que quelque chose a bougé de façon inattendue.
Hashes SRI vs sources hash CSP
Ils se ressemblent trait pour trait et signifient des choses différentes, donc autant les tenir séparés.
| Hash SRI | Source hash CSP | |
|---|---|---|
| Vit sur | L'attribut integrity d'un élément | Une source script-src / style-src dans la politique |
| Hache | Les octets d'une ressource externe chargée par URL | Le contenu texte d'un élément inline |
| Préfixe | sha256- / sha384- / sha512- | sha256- / sha384- / sha512- |
Les deux utilisent le même préfixe base64 sha256-, sha384-, sha512-, mais
l'entrée diffère : SRI hache le corps de réponse d'une ressource chargée depuis une
URL, tandis qu'une source hash
CSP hache le contenu inline d'un élément pour que la politique puisse l'autoriser. La
même chaîne au mauvais endroit ne fera pas ce que vous attendez.
Exiger SRI avec Integrity-Policy
SRI est un opt-in par élément. Rien n'empêche un développeur d'ajouter un nouveau
script externe sans attribut integrity. Le
header Integrity-Policy comble cette
lacune : il demande au navigateur de bloquer toute ressource d'une destination donnée
qui se charge sans métadonnées d'intégrité valides.
Integrity-Policy: blocked-destinations=(script), endpoints=(integrity-endpoint)Vous câblez l'endpoint nommé via un header
Reporting-Endpoints :
Reporting-Endpoints: integrity-endpoint="https://<Endpoint-ID>.report.centralcsp.com"Un script sans intégrité valide est alors bloqué, et le navigateur émet un
rapport integrity-violation
vers cet endpoint. Une variante report-only, Integrity-Policy-Report-Only, signale
les mêmes violations sans bloquer, pour mesurer la couverture avant d'appliquer.
SRI et CSP
SRI et CSP sont des contrôles orthogonaux que vous exécutez ensemble. CSP décide si un script a le droit de s'exécuter tout court et comment la confiance se propage entre les scripts. SRI vérifie que les octets d'un script autorisé sont exactement ceux que vous attendiez. Un script peut passer CSP et être altéré quand même ; SRI est ce qui l'attrape.
L'ancienne façon de les combiner était la directive CSP require-sri-for, qui aurait
imposé des métadonnées d'intégrité sur les scripts ou les styles. Elle n'a jamais été
livrée dans un navigateur stable et est abandonnée, donc n'y touchez pas. Son rôle
est désormais tenu par le header Integrity-Policy ci-dessus.
Outillage de build
Générer et maintenir des hashes à la main ne passe pas à l'échelle, laissez donc le bundler les émettre :
- Webpack a le plugin
webpack-subresource-integrity, qui écrit les attributsintegrityautomatiquement et gère les imports dynamiques du code-splitting. - Vite ne livre pas de SRI de première main, utilisez donc un plugin
communautaire comme
@small-tech/vite-plugin-sri.
Prise en charge par les navigateurs
L'attribut integrity de base sur les scripts et les feuilles de style est largement
pris en charge dans les navigateurs modernes. La directive CSP require-sri-for n'a
jamais été livrée et est morte. Le header Integrity-Policy est récent :
l'application pour la destination script est livrée dans Chrome, Firefox et Safari,
mais il n'est pas encore Baseline.
Voir aussi
- Integrity-Policy
- rapport integrity-violation
- Hashes et nonces CSP
- Header Reporting-Endpoints
- Subresource Integrity expliqué
- Comment générer un hash SRI