# Ce que fait unsafe-eval en CSP et comment le retirer (/fr/blog/unsafe-eval-csp)





Si votre politique de sécurité du contenu (CSP) contient `'unsafe-eval'`, vous laissez la page transformer des chaînes arbitraires en code exécuté. La CSP est un header de réponse HTTP qui indique au navigateur quels scripts il a le droit d'exécuter, et par défaut elle bloque les fonctions qui compilent une chaîne en JavaScript exécutable. Le mot-clé `'unsafe-eval'` désactive de nouveau ce blocage.

En résumé : ne déployez pas `'unsafe-eval'` dans une directive de script. Trouvez ce qui en dépend (le plus souvent une fonctionnalité de framework ou un snippet injecté), passez à un build qui n'a pas besoin de compiler du code au runtime, et si vous n'avez besoin que de WebAssembly, utilisez plutôt le plus restreint `'wasm-unsafe-eval'`. La suite de cet article explique ce que le mot-clé autorise, pourquoi il affaiblit la politique, où il a tendance à se glisser, et comment s'en passer en commençant par Report-Only.

Vous débutez avec la CSP ? [Démarrer avec la politique de sécurité du contenu](/fr/blog/get-started-with-csp) couvre d'abord les bases. Pour le problème connexe des scripts inline, voyez [pourquoi ne jamais utiliser unsafe-inline en CSP](/fr/blog/unsafe-inline-csp).

## Que fait 'unsafe-eval' ? [#que-fait-unsafe-eval-]

Par défaut, une CSP qui définit `script-src` bloque toutes les API qui compilent une chaîne en code. Ajouter `'unsafe-eval'` à cette directive les réactive. Les fonctions qu'elle débloque sont :

* `eval("...")`, qui exécute une chaîne comme du JavaScript.
* Le constructeur `Function`, `new Function("a", "return a + 1")`, qui construit une fonction à partir d'une source en chaîne.
* `setTimeout("code", 0)` et `setInterval("code", 0)` quand le premier argument est une chaîne plutôt qu'une fonction.
* La compilation et l'instanciation de WebAssembly, qui historiquement nécessitaient aussi `'unsafe-eval'`.

Quand `'unsafe-eval'` est absent, le navigateur lève une erreur sur chacune de ces opérations et signale une violation. Passer une fonction à `setTimeout` continue de fonctionner ; seule la forme en chaîne est concernée.

## Pourquoi il affaiblit la politique [#pourquoi-il-affaiblit-la-politique]

Tout l'intérêt d'une CSP stricte est que le navigateur n'exécute que le code que vous avez marqué comme de confiance, via un nonce ou un hash. Les API qui transforment des chaînes en code contournent cela. Une fois `eval` autorisé, toute chaîne contrôlée par l'attaquant qui atteint un sink `eval` devient du code exécuté, ce qui est précisément le point d'appui que recherchent la plupart des attaques de cross-site scripting (XSS).

Une chaîne d'attaque réelle ressemble à ceci : une saisie utilisateur arrive dans une valeur qu'une bibliothèque passe ensuite à `eval` ou `new Function` (un compilateur de templates, un évaluateur d'expressions, un parseur de config). Sans `'unsafe-eval'`, le navigateur refuse de la compiler. Avec `'unsafe-eval'` présent, la chaîne injectée s'exécute avec tous les privilèges de la page, et la protection par nonce ou hash que vous avez mise en place n'y change rien.

La CSP est une défense en profondeur, pas un remplacement du traitement des entrées. Vous continuez à valider et à échapper. `'unsafe-eval'` supprime la couche qui contient les dégâts quand quelque chose passe à travers.

## Où 'unsafe-eval' se glisse [#où-unsafe-eval-se-glisse]

La plupart des équipes n'ajoutent pas `'unsafe-eval'` volontairement. Il s'insinue parce qu'un outil en a besoin :

* **Frameworks front-end en mode JIT.** [Angular](https://angular.dev/) avec le compilateur just-in-time compile les templates au runtime par génération de code. [Vue](https://vuejs.org/) avec le build à compilateur runtime (templates compilés dans le navigateur) fait de même. Les deux n'ont besoin de `'unsafe-eval'` que dans ces modes.
* **Tag managers avec du JavaScript personnalisé.** Les variables custom HTML et custom JavaScript de [Google Tag Manager](https://developers.google.com/tag-platform/tag-manager) évaluent des chaînes, ce qui entraîne `'unsafe-eval'`. Voyez [faire tourner Google Analytics et Tag Manager sous une CSP stricte](/fr/blog/csp-google-analytics-tag-manager) pour les contournements.
* **Anciens bundlers et builds de développement.** Certains builds de développement et configurations de source-map utilisent `eval` pour envelopper les modules. Les builds de production ne le font généralement pas, donc c'est souvent une fuite limitée au développement qui ne devrait jamais atteindre les headers de production.
* **Bibliothèques de graphiques, d'expressions et de templating.** Une bibliothèque qui laisse les utilisateurs écrire des formules ou des templates peut les compiler avec `new Function`. Vérifiez la bibliothèque avant d'autoriser `eval` pour elle.
* **WebAssembly.** Compiler un module `.wasm` comptait autrefois comme un `eval` du point de vue de la CSP, donc tout code utilisant WASM entraînait `'unsafe-eval'`.

## Comment le retirer [#comment-le-retirer]

La correction consiste presque toujours à cesser de compiler du code au runtime, pas à garder le mot-clé. Si vous ne pouvez pas encore retirer un sink eval, [activez les Trusted Types](/fr/blog/enable-trusted-types) pour que la compilation de chaîne restante doive d'abord passer par une policy.

### Passez les frameworks en builds ahead-of-time (AOT) [#passez-les-frameworks-en-builds-ahead-of-time-aot]

Le build de production par défaut d'Angular est AOT : les templates sont compilés pendant le build, donc le navigateur ne compile rien et `'unsafe-eval'` n'est pas nécessaire. Assurez-vous de ne pas déployer un build JIT en production. Pour Vue, utilisez le build runtime-only et précompilez les templates avec l'outillage de build plutôt qu'avec le compilateur runtime.

```http
Content-Security-Policy: script-src 'self' 'nonce-r4nd0m' 'strict-dynamic'
```

C'est l'objectif : une directive de script sans aucun `'unsafe-eval'`, qui fait confiance aux scripts via un nonce et `'strict-dynamic'`. Pour savoir comment ce mot-clé propage la confiance, voyez [le guide strict-dynamic](/fr/blog/strict-dynamic-csp).

### Remplacez le code basé sur eval [#remplacez-le-code-basé-sur-eval]

Pour votre propre code, les formes en chaîne ont des remplacements directs :

```javascript
// Before: needs 'unsafe-eval'
setTimeout("doWork()", 1000); // [!code --]
const add = new Function("a", "b", "return a + b"); // [!code --]

// After: works under a strict policy, no 'unsafe-eval'
setTimeout(() => doWork(), 1000); // [!code ++]
const add = (a, b) => a + b; // [!code ++]
```

Passez une fonction à `setTimeout` et `setInterval`. Remplacez `new Function` par une vraie fonction ou une petite table de correspondance d'opérations connues. Parsez la config JSON avec `JSON.parse`, jamais `eval`.

### Déplacez l'évaluation des templates ou expressions au moment du build [#déplacez-lévaluation-des-templates-ou-expressions-au-moment-du-build]

Si une bibliothèque compile des templates ou des expressions dans le navigateur, passez à son mode précompilé ou précalculez les valeurs pendant votre build, de sorte que rien n'atteigne un sink `eval` au runtime.

## L'option plus restreinte, 'wasm-unsafe-eval' [#loption-plus-restreinte-wasm-unsafe-eval]

Si la seule raison pour laquelle vous aviez besoin de `'unsafe-eval'` était WebAssembly, il existe un mot-clé bien plus restreint. `'wasm-unsafe-eval'` autorise la compilation et l'instanciation de modules WASM mais ne réactive **pas** `eval`, `new Function` ni les timers à chaîne. C'est le bon choix quand vous déployez un module WASM et voulez que tout le reste reste bloqué.

```http
Content-Security-Policy: script-src 'self' 'wasm-unsafe-eval'
```

Utilisez `'wasm-unsafe-eval'` au lieu de `'unsafe-eval'` chaque fois que WASM est votre seul besoin. Il est largement pris en charge par les navigateurs actuels. `'unsafe-eval'` autorise bien la compilation WebAssembly, mais il réactive aussi `eval`, `new Function` et les timers à chaîne, donc l'utiliser juste pour WASM est plus large que nécessaire. `'wasm-unsafe-eval'` est le mot-clé plus restreint qui n'autorise que la compilation WASM et laisse tout le reste bloqué.

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

## Un chemin de migration sûr hors de 'unsafe-eval' [#un-chemin-de-migration-sûr-hors-de-unsafe-eval]

Retirer `'unsafe-eval'` peut casser tout ce qui s'appuyait discrètement dessus, alors avancez par étapes et surveillez les reports avant d'appliquer l'enforcement. C'est la même approche Report-Only d'abord que [mode enforce vs Report-Only](/fr/blog/csp-enforce-vs-report-only).

1. **Trouvez l'usage d'eval.** Cherchez dans votre bundle et vos dépendances `eval(`, `new Function(`, et les `setTimeout`/`setInterval` à chaîne. L'[évaluateur CSP](/tools/csp-evaluator) signale quand une politique en production porte encore `'unsafe-eval'`.
2. **Corrigez chaque cas.** Passez les frameworks en AOT, remplacez les timers à chaîne et `new Function`, et faites passer WASM à `'wasm-unsafe-eval'`.
3. **Testez en Report-Only.** Déployez la politique sans `'unsafe-eval'` sur le header `Content-Security-Policy-Report-Only`. Le navigateur ne bloque rien, il signale seulement ce qu'il bloquerait, vous voyez donc chaque sink eval restant sur le trafic réel.
4. **Appliquez l'enforcement.** Quand le Report-Only est silencieux, déplacez la même politique vers le header `Content-Security-Policy` qui applique l'enforcement.

CentralCSP collecte ces reports Report-Only pour vous, les regroupe, et montre les scripts qui tournent sur chaque page, pour que vous puissiez identifier quelle dépendance appelle encore `eval` avant de basculer en enforcement. C'est le cœur de la [suite CSP](/platform/csp-builder). Vous pouvez [démarrer un essai gratuit](/register) et y pointer un header Report-Only pour suivre la migration.

Pour la référence complète des directives et des mots-clés, voyez la [référence de la politique CSP](/fr/docs/web-security/policies/content-security-policy).

## Questions fréquentes [#questions-fréquentes]

### Peut-on garder 'unsafe-eval' sans risque ? [#peut-on-garder-unsafe-eval-sans-risque-]

Non. Il réactive la compilation de chaîne en code pour n'importe quelle chaîne, ce qui est le comportement dont abusent la plupart des attaques XSS. Retirez-le et utilisez des builds AOT, des fonctions classiques, et `'wasm-unsafe-eval'` pour WebAssembly.

### Quelle est la différence entre 'unsafe-eval' et 'wasm-unsafe-eval' ? [#quelle-est-la-différence-entre-unsafe-eval-et-wasm-unsafe-eval-]

`'unsafe-eval'` autorise `eval`, `new Function` et les timers à chaîne ainsi que WebAssembly. `'wasm-unsafe-eval'` n'autorise que la compilation WebAssembly et laisse le reste bloqué, c'est donc le choix plus restreint et plus sûr quand WASM est tout ce dont vous avez besoin.

### Angular a-t-il besoin de 'unsafe-eval' ? [#angular-a-t-il-besoin-de-unsafe-eval-]

Seulement en mode just-in-time. Le build AOT de production par défaut compile les templates au moment du build, il n'a donc pas besoin de `'unsafe-eval'`. Vérifiez que vous ne déployez pas un build JIT en production.

## Sources [#sources]

* [MDN, script-src directive](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/script-src)
* [MDN, CSP guide](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP)
* [W3C CSP Level 3 specification](https://www.w3.org/TR/CSP3/)
* [Angular security guide](https://angular.dev/best-practices/security)

## À lire aussi [#à-lire-aussi]

* [Pourquoi ne jamais utiliser unsafe-inline en CSP](/fr/blog/unsafe-inline-csp)
* [strict-dynamic expliqué](/fr/blog/strict-dynamic-csp)
* [trusted-types-eval, une façon plus sûre d'autoriser eval en CSP](/fr/blog/trusted-types-eval-csp)
