# Le schéma blob dans la Content Security Policy (/fr/blog/csp-blob-scheme)





Si votre page crée un Web Worker ou lit un média depuis une URL `blob:`, la Content Security Policy (CSP) va le bloquer tant que vous n'avez pas listé `blob:` sur la bonne directive. La CSP est un header de réponse HTTP qui indique au navigateur quelles ressources une page a le droit de charger. Le piège qui surprend la plupart des gens : le mot-clé `'self'` et le wildcard `*` ne correspondent pas à `blob:`. Vous devez l'autoriser nommément.

En résumé : `blob:` est une source de schéma, comme `https:` ou `data:`. Pour autoriser un worker construit à partir d'un blob, vous écrivez `worker-src 'self' blob:` ; pour autoriser un script blob, vous écrivez `script-src 'self' blob:`. Mais autoriser `blob:` dans un contexte de script laisse la page exécuter du code qu'elle fabrique à l'exécution, ce qui revient presque à rétablir `'unsafe-eval'`. Autorisez-le donc là où vous devez le faire (workers, médias), et tenez-le à l'écart des directives de script partout où c'est possible.

Vous débutez avec ce header ? [Démarrer avec la Content Security Policy](/fr/blog/get-started-with-csp) couvre votre première politique avant que vous n'ajustiez les cas limites.

## Qu'est-ce qu'une URL blob ? [#quest-ce-quune-url-blob-]

Une URL `blob:` pointe vers un objet `Blob` ou `File` conservé en mémoire par le navigateur. JavaScript en crée une à l'exécution avec `URL.createObjectURL()`, et le résultat ressemble à `blob:https://example.com/9d3a...`. L'URL est opaque et éphémère, et elle n'existe que dans cette page. Vous ne pouvez pas l'héberger, l'autoriser par hôte, ni la verrouiller avec un hash.

Les pages utilisent les URL blob pour des tâches légitimes : générer un fichier à télécharger, diffuser de l'audio ou de la vidéo enregistrés, ou lancer un Web Worker à partir de code assemblé à la volée. Voici le cas du worker, celui sur lequel la CSP achoppe le plus souvent.

```html
<script>
  // Worker code assembled at runtime, then run from a blob: URL
  const workerCode = `
    self.onmessage = (event) => {
      const sum = event.data.reduce((acc, value) => acc + value, 0);
      postMessage(sum);
    };
  `;
  const workerBlob = new Blob([workerCode], { type: "application/javascript" });
  const workerUrl = URL.createObjectURL(workerBlob);

  const worker = new Worker(workerUrl);
  worker.onmessage = (event) => console.log("sum:", event.data);
  worker.postMessage([1, 2, 3, 4, 5]);
</script>
```

Avec une politique stricte en place, cet appel `new Worker(workerUrl)` échoue tant que la politique n'autorise pas `blob:`.

## Quelle directive gouverne blob [#quelle-directive-gouverne-blob]

La directive dépend de l'usage du blob.

Pour un worker, la directive [`worker-src`](/fr/docs/web-security/policies/content-security-policy/directives/worker-src) s'applique aux scripts `Worker`, `SharedWorker` et `ServiceWorker`. Si `worker-src` est absent, le navigateur redescend une chaîne de repli : `worker-src`, puis [`child-src`](/fr/docs/web-security/policies/content-security-policy/directives/child-src), puis [`script-src`](/fr/docs/web-security/policies/content-security-policy/directives/script-src), puis `default-src`. Un worker construit à partir de `URL.createObjectURL()` est donc vérifié contre celle de ces directives qui est présente en premier. Si votre seule directive de script est `script-src 'self'` sans `worker-src`, le worker est vérifié contre `script-src`, et le `blob:` est bloqué.

Un worker bloqué n'est pas un échec en douceur. Le navigateur traite la requête refusée comme une erreur réseau fatale, donc le worker ne s'exécute tout simplement jamais.

Pour un script chargé depuis un blob (un `<script src="blob:...">` ou tout fetch de blob typé comme script), la directive qui gouverne est `script-src`, avec un repli sur `default-src`.

Les médias et les images suivent le même motif de source de schéma sur leur propre directive :

```http
Content-Security-Policy: media-src 'self' blob:
```

```http
Content-Security-Policy: img-src 'self' blob:
```

## Pourquoi self et le wildcard ne couvrent pas blob [#pourquoi-self-et-le-wildcard-ne-couvrent-pas-blob]

C'est la partie qui surprend. Une URL `blob:` de même origine n'est **pas** couverte par le [mot-clé `'self'`](/fr/docs/web-security/policies/content-security-policy/values/csp-keywords). Même si le blob partage votre origine, vous devez quand même lister `blob:` explicitement.

Le wildcard `*` n'aide pas non plus. L'algorithme de correspondance de la liste de sources CSP exclut `blob:`, `data:` et `filesystem:` d'un simple `*`. Donc `default-src *` n'autorise pas `blob:`. Ces schémas sont traités à part parce que ce sont des schémas locaux qui produisent du contenu depuis la page elle-même plutôt que depuis un hôte réseau.

Cela signifie qu'une politique comme `script-src 'self'`, ou même `script-src *`, bloquera un worker blob ou un script blob. Pour l'autoriser, nommez le schéma en tant que [source de schéma](/fr/docs/web-security/policies/content-security-policy/values/csp-scheme-source) :

```http
Content-Security-Policy: worker-src 'self' blob:
```

Notez que `blob:` s'écrit sans quotes, avec les deux-points finaux. C'est une source de schéma, pas un mot-clé, donc il ne prend jamais les quotes simples qu'utilisent `'self'` ou `'unsafe-inline'`.

Tous les principaux navigateurs se comportent ainsi aujourd'hui. (D'anciennes versions de Chrome ont un temps considéré que `'self'` couvrait les scripts `blob:` de même origine, ce qui contredisait la spec ainsi que Firefox et WebKit. Chrome actuel exige `blob:` explicitement, vous pouvez donc compter sur la même règle partout.)

## À quoi ressemble un blob bloqué dans les reports [#à-quoi-ressemble-un-blob-bloqué-dans-les-reports]

Une ressource `blob:` refusée produit un report de violation CSP standard, sans forme particulière. Le champ `effectiveDirective` du report reflète la directive qui l'a bloquée, par exemple `worker-src` ou `script-src`. L'URL bloquée est généralement reportée comme le schéma `blob` plutôt que sous la forme de l'URL opaque complète, parce que le navigateur assainit les URI bloquées. Les [champs d'un report de violation CSP](/fr/blog/csp-violation-report-fields) expliquent ce que signifie chacune de ces valeurs. La chaîne `blockedURL` exacte qu'un navigateur reporte pour une ressource `blob:` peut varier, donc basez votre traitement sur `effectiveDirective` plutôt que sur l'URL.

Si vous ne collectez pas encore ces reports, [démarrer avec le reporting CSP](/fr/blog/get-started-csp-reporting) détaille le câblage d'un endpoint `report-to` pour que les blobs bloqués apparaissent au lieu d'échouer en silence. Un endpoint de reporting ressemble à `https://<Endpoint-ID>.report.centralcsp.com`.

<img alt="Des lignes de violation dont l'origine bloquée est un schéma plutôt qu'un hôte" src="__img0" width="1359" height="208" />

## Le risque côté script [#le-risque-côté-script]

Une page peut assembler du code arbitraire dans un `Blob` et l'exécuter comme worker ou comme script via son URL blob. Autoriser `blob:` sur `script-src` ou `worker-src` laisse donc la page exécuter du code qu'elle construit à l'exécution. En pratique, cela affaiblit la politique d'une manière comparable à `'unsafe-eval'` : si un attaquant prend pied (via une faille XSS ou une dépendance compromise), il peut construire un blob malveillant et le charger comme script, et la politique le laisse passer parce que la source est `blob:`, et non parce que quelqu'un en a examiné le contenu.

```html
<!-- If script-src allows blob:, this runs. Any script on the page could do it. -->
<script>
  const code = "console.log('arbitrary code via blob:', document.domain)";
  const blob = new Blob([code], { type: "text/javascript" });
  const s = document.createElement("script");
  s.src = URL.createObjectURL(blob);
  document.body.appendChild(s);
</script>
```

Le contenu d'un blob est généré à l'exécution, il est donc aussi difficile à auditer. Il n'y a pas de fichier statique à examiner, ni d'hôte ou de hash sur lequel le verrouiller. C'est le compromis que vous acceptez quand `blob:` figure dans une directive de script.

## Comment tenir blob à l'écart des contextes de script [#comment-tenir-blob-à-lécart-des-contextes-de-script]

L'objectif est d'autoriser `blob:` seulement là où il ne peut pas exécuter de code, et de servir scripts et workers depuis de vraies URL que vous contrôlez.

1. Servez les scripts de worker depuis un chemin statique plutôt qu'un blob. Un fichier en `/static/workers/task.js` peut être autorisé par hôte, et il survit à une politique plus stricte.
2. Autorisez vos propres scripts inline avec un nonce ou un hash plutôt qu'un schéma. Les [valeurs nonce et hash](/fr/docs/web-security/policies/content-security-policy/values/csp-hashes-nonce) vous permettent d'approuver des scripts précis par leur identité, ce que `blob:` ne peut pas faire.
3. Réservez `blob:` aux directives non exécutantes comme `media-src` ou `img-src` quand votre application en a réellement besoin pour la lecture ou l'affichage d'images.

Un worker chargé depuis une URL statique n'a aucun besoin de blob :

```html
<script>
  const worker = new Worker("/static/workers/task.js");
  worker.postMessage([1, 2, 3, 4, 5]);
</script>
```

La politique qui en résulte limite l'exécution des scripts et des workers à votre origine, et n'autorise `blob:` que pour les médias :

```http
Content-Security-Policy: default-src 'self';
    script-src 'self';
    worker-src 'self';
    media-src 'self' blob:
```

Si vous avez vraiment besoin d'un worker blob et ne pouvez pas le déplacer vers un fichier statique, cadrez l'autorisation au plus serré : mettez `blob:` sur `worker-src` uniquement, pour qu'il n'élargisse jamais ce que `script-src` accepte.

## Déployez-la d'abord en Report-Only [#déployez-la-dabord-en-report-only]

Avant d'imposer une politique qui retire `blob:` des directives de script et de worker, faites-la tourner en mode observation pour voir ce qui casserait. Le [header Content-Security-Policy-Report-Only](/fr/docs/web-security/policies/content-security-policy/report-only) reporte les violations sans rien bloquer. Surveillez les workers blob bloqués, corrigez les cas légitimes en servant le worker depuis une URL statique, puis basculez en mode enforce.

Quand vous auditez ce que votre site autorise déjà, notre [scanner CSP](/tools/csp-scanner) montre la politique en vigueur sur une page et signale les endroits où `blob:` se trouve dans une directive risquée, pour que vous puissiez la resserrer avant qu'un attaquant ne le découvre.

## Référence rapide [#référence-rapide]

* `blob:` est une source de schéma. Écrivez-le sans quotes, avec les deux-points : `worker-src 'self' blob:`.
* Ni `'self'` ni `*` ne correspondent à `blob:`. Autorisez-le nommément.
* Les workers résolvent `worker-src`, puis `child-src`, puis `script-src`, puis `default-src`. Un worker bloqué est une erreur réseau fatale.
* Les scripts résolvent `script-src`, puis `default-src`.
* Autoriser `blob:` dans une directive de script revient presque à `'unsafe-eval'`. Tenez-le à l'écart de `script-src` et `worker-src` partout où c'est possible ; servez plutôt les workers depuis des URL statiques.

Vous voulez durcir le reste du header ensuite ? [Comment construire une CSP solide](/fr/blog/how-to-build-a-strong-csp) couvre les nonces, les hashes, et la suppression des mots-clés qui affaiblissent la politique.

## Articles liés [#articles-liés]

* [Le schéma data dans la Content Security Policy](/fr/blog/csp-data-scheme)
* [Construire une CSP solide, étape par étape](/fr/blog/how-to-build-a-strong-csp)
