CentralCSP
Autres

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 sha256 et un token sha512, 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 integrity du header HTTP Link, l'équivalent par header d'un preload.
  • Les modules ES importés dynamiquement, via le champ integrity d'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 SRISource hash CSP
Vit surL'attribut integrity d'un élémentUne source script-src / style-src dans la politique
HacheLes octets d'une ressource externe chargée par URLLe contenu texte d'un élément inline
Préfixesha256- / 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 :

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

Sources

On this page