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



Le schéma `data:` permet à une URL de transporter son propre contenu en inline : `data:image/png;base64,...` contient à lui seul une image entière, sans serveur à interroger. Dans une politique de sécurité du contenu (CSP), vous pouvez autoriser ce schéma directive par directive. Pour les images et les polices, c'est pratique et courant. Pour les scripts, cela donne à un attaquant un moyen d'exécuter du code sans le moindre hôte externe.

Cet article montre où `data:` a sa place dans une politique, où il n'en a pas, et pourquoi la différence compte.

## À quoi ressemble le schéma data dans une CSP [#à-quoi-ressemble-le-schéma-data-dans-une-csp]

`data:` est une [source de schéma](/fr/docs/web-security/policies/content-security-policy/values/csp-scheme-source). La grammaire attend le nom du schéma suivi de deux-points : vous écrivez donc `data:` tel quel, avec le deux-points final et sans guillemets, contrairement aux sources par mot-clé comme `'self'`.

L'usage courant et raisonnable concerne les images et les polices en inline :

```http
Content-Security-Policy: img-src 'self' data:; font-src 'self' data:
```

Cela autorise [`img-src`](/fr/docs/web-security/policies/content-security-policy/directives/img-src) et [`font-src`](/fr/docs/web-security/policies/content-security-policy/directives/font-src) à charger des ressources depuis votre propre origine et depuis des data URI en inline, ce qui permet l'affichage des icônes en base64, des petites images de remplacement et des polices embarquées.

Chaque directive est indépendante. Une directive n'autorise `data:` que si vous l'y écrivez, et il ne s'y glisse ni par un fallback ni par un wildcard (nous y revenons plus bas).

## Pourquoi data est sûr pour les images mais dangereux pour les scripts [#pourquoi-data-est-sûr-pour-les-images-mais-dangereux-pour-les-scripts]

Une image `data:` ne peut pas exécuter de code. Ce sont des octets que le navigateur décode et affiche. Un script `data:` est différent : l'URL transporte le corps du script, donc toute la charge utile tient dans l'expression de source.

Si [`script-src`](/fr/docs/web-security/policies/content-security-policy/directives/script-src) autorise ce schéma, un attaquant capable d'injecter une seule balise `<script>` n'a plus rien à héberger. Le code tient dans l'URL :

```html
<script src="data:text/javascript,alert(document.domain)"></script>
<script src="data:;base64,YWxlcnQoMSk="></script>
```

Les versions actuelles de Chrome, Firefox et Safari exécutent les scripts `data:` externes, donc c'est un vecteur d'exécution opérationnel aujourd'hui, pas une bizarrerie héritée du passé. Les analyses de risque présentent `data:` dans `script-src` comme un contournement de CSP. La spécification, elle, se contente de définir la correspondance des schémas et n'en fait pas un avertissement XSS. Voyez donc ce danger comme une recommandation de durcissement, pas comme une règle de la spec.

Une précision s'impose. Les navigateurs bloquent la navigation de premier niveau vers une URL `data:`, un changement anti-phishing plus ancien, mais cela ne bloque pas les sous-ressources `data:` comme `<script src="data:...">` ou `<img src="data:...">`. Le script se charge en sous-ressource dans la propre origine de la page, donc le blocage de navigation ne s'applique pas.

## Le wildcard ne couvre pas data [#le-wildcard-ne-couvre-pas-data]

On suppose naturellement que `script-src *` autorise tout, y compris `data:`. Ce n'est pas le cas. En CSP Level 3, un simple `*` ne correspond à une URL que lorsque celle-ci utilise un schéma HTTP ou HTTPS (plus le même schéma que le document protégé). Les schémas `data:`, `blob:` et `filesystem:` sont exclus et doivent être listés explicitement.

```http
Content-Security-Policy: script-src *
```

Cette politique n'autorise pas les scripts `data:`. Il faudrait l'ajouter vous-même pour qu'ils s'exécutent, et c'est précisément pour ça qu'il ne faut pas le faire.

Cette exclusion est un correctif de sécurité délibéré. Les navigateurs ont restreint la correspondance de `data:` après la confirmation d'un contournement réel par wildcard, et ils se comportent tous de la même façon aujourd'hui.

## Où autoriser data, et où ne pas le faire [#où-autoriser-data-et-où-ne-pas-le-faire]

Décidez directive par directive, selon que la directive peut ou non mener à l'exécution de code :

* [`img-src`](/fr/docs/web-security/policies/content-security-policy/directives/img-src), `font-src` et [`media-src`](/fr/docs/web-security/policies/content-security-policy/directives/media-src) : autoriser `data:` est légitime et très répandu pour les ressources en base64 en inline.
* [`script-src`](/fr/docs/web-security/policies/content-security-policy/directives/script-src) : n'autorisez pas `data:`. C'est un vecteur d'exécution XSS, comme montré plus haut.
* [`object-src`](/fr/docs/web-security/policies/content-security-policy/directives/object-src) et `frame-src` : risqués également, puisque des plugins ou des frames `data:` peuvent transporter du contenu actif.
* `style-src` : déconseillé. Une feuille de style `data:` contrôlée par un attaquant se charge comme une sous-ressource et s'applique, ce qui ouvre un vrai vecteur d'injection et d'exfiltration par CSS (mais pas d'exécution de code).
* [`default-src`](/fr/docs/web-security/policies/content-security-policy/directives/default-src) : particulièrement néfaste. En l'absence de `script-src`, c'est `default-src` qui régit les scripts, donc `default-src data:` permet de fait les scripts `data:`.

Une grande partie des sites autorisait historiquement `data:` sous `script-src`, `frame-src` ou `object-src` (ou `default-src` lorsque `script-src` était absent), et c'est pourquoi cela reste un constat fréquent.

## L'alternative plus sûre pour les scripts [#lalternative-plus-sûre-pour-les-scripts]

Le correctif n'est pas de trouver une manière prudente d'autoriser `data:` dans `script-src`. C'est d'arrêter complètement d'autoriser les scripts par schéma ou par hôte, et de passer au [nonce ou au hash](/fr/docs/web-security/policies/content-security-policy/values/csp-hashes-nonce), avec [`'strict-dynamic'`](/fr/blog/strict-dynamic-csp).

Les recommandations de Chrome et de Google sont explicites : les allowlists par hôte et par schéma offrent peu de protection, et un nonce ou un hash plus `'strict-dynamic'` est le modèle à adopter. Une politique stricte minimale ressemble à ceci :

```http
Content-Security-Policy: script-src 'nonce-r4nd0m' 'strict-dynamic';
    object-src 'none';
    base-uri 'none'
```

Avec un nonce en place, le navigateur ne fait confiance qu'aux scripts portant ce nonce et aux scripts que ces scripts de confiance chargent. Un script `data:` sans nonce correspondant est rejeté, donc le contournement se referme même si un attaquant injecte une balise. Pour l'argumentaire général contre ce genre d'ouverture dans la politique, voyez [pourquoi supprimer `'unsafe-inline'` compte](/fr/blog/unsafe-inline-csp) et la démonstration plus complète dans [comment construire une CSP solide](/fr/blog/how-to-build-a-strong-csp).

Si vous avez besoin de quelques images ou polices en base64 en inline, gardez `data:` cantonné à `img-src` et `font-src` et laissez-le hors de tout ce qui touche au script ou au style.

## Repérer data dans votre propre politique [#repérer-data-dans-votre-propre-politique]

Procédez prudemment : placez d'abord la politique candidate sur le header [`Content-Security-Policy-Report-Only`](/fr/docs/web-security/policies/content-security-policy/report-only), surveillez les reports, et ne l'appliquez qu'une fois qu'ils se taisent. Pour savoir où en est votre politique en production aujourd'hui, passez-la dans l'[évaluateur CSP](/tools/csp-evaluator), qui signale `data:` dans `script-src` et d'autres sources faibles afin que vous sachiez quoi resserrer avant qu'elles ne deviennent une porte d'entrée.

L'évaluateur lit la politique que vous livrez déjà. Ce qu'il ne peut pas vous dire, c'est quelles URI `data:` vos pages chargent réellement, car cela n'apparaît qu'à l'exécution. CentralCSP collecte les reports csp-violation issus de vraies visites et les regroupe par URI bloquée, si bien qu'en retirant `data:` de `script-src`, vous voyez exactement quels payloads inline cessent de se charger, et si certains étaient les vôtres.

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

* [Le schéma blob dans la Content Security Policy](/fr/blog/csp-blob-scheme)
* [Pourquoi ne jamais utiliser unsafe-inline dans une CSP](/fr/blog/unsafe-inline-csp)
