# Subresource Integrity (/fr/docs/web-security/other/subresource-integrity)



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.

<Callout type="warn" title="Une directive est morte, une autre est la voie moderne">
  L'ancienne directive CSP [`require-sri-for`](/fr/docs/web-security/policies/content-security-policy/directives/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`](/fr/docs/web-security/policies/integrity-policy), qui est récent et pas encore Baseline. Voir [Prise en charge par les navigateurs](#prise-en-charge-par-les-navigateurs).
</Callout>

## Un exemple minimal [#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.

```html
<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 [#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.

```html
<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 [#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](/tools/sri-hash), 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 [#lexigence-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.

```http
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 [#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](/platform/supply-chain) 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 [#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](/fr/docs/web-security/policies/content-security-policy/values/csp-hashes-nonce)
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 [#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`](/fr/docs/web-security/policies/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.

```http
Integrity-Policy: blocked-destinations=(script), endpoints=(integrity-endpoint)
```

Vous câblez l'endpoint nommé via un header
[`Reporting-Endpoints`](/fr/docs/web-security/reporting-api/headers/reporting-endpoints) :

```http
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](/fr/docs/web-security/reporting-api/reports/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]

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 [#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`](https://www.npmjs.com/package/webpack-subresource-integrity),
  qui écrit les attributs `integrity` automatiquement 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`](https://www.npmjs.com/package/@small-tech/vite-plugin-sri).

## Prise en charge par les navigateurs [#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 [#voir-aussi]

* [Integrity-Policy](/fr/docs/web-security/policies/integrity-policy)
* [rapport integrity-violation](/fr/docs/web-security/reporting-api/reports/integrity-violation)
* [Hashes et nonces CSP](/fr/docs/web-security/policies/content-security-policy/values/csp-hashes-nonce)
* [Header Reporting-Endpoints](/fr/docs/web-security/reporting-api/headers/reporting-endpoints)
* [Subresource Integrity expliqué](/fr/blog/subresource-integrity-sri)
* [Comment générer un hash SRI](/fr/blog/generate-sri-hash)

## Sources [#sources]

* [W3C, Subresource Integrity](https://www.w3.org/TR/SRI/)
* [MDN, Subresource Integrity](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity)
* [MDN, Integrity-Policy header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Integrity-Policy)
