# Comment activer Trusted Types avec une CSP pour stopper le XSS DOM (/fr/blog/enable-trusted-types)



Trusted Types est la partie d'une politique de sécurité du contenu (CSP) qui ferme le cross-site scripting (XSS) basé sur le DOM. Une CSP est un header de réponse HTTP qui indique au navigateur quels scripts peuvent s'exécuter, et Trusted Types étend cela aux sinks du DOM qui transforment une chaîne en markup ou en code vivant : `innerHTML`, `document.write`, `eval`, le constructeur `Function`, et quelques dizaines d'autres. Avec Trusted Types appliqué, ces sinks rejettent une chaîne brute. Les seules valeurs qu'ils acceptent sont des objets typés produits par vos propres politiques, donc une chaîne injectée n'atteint jamais un sink.

La version courte : réglez [`require-trusted-types-for`](/fr/docs/web-security/policies/content-security-policy/directives/require-trusted-types-for) sur `'script'` pour activer l'application, utilisez la directive [`trusted-types`](/fr/docs/web-security/policies/content-security-policy/directives/trusted-types) pour autoriser les noms de politiques qui peuvent créer ces valeurs typées, et déployez d'abord en Report-Only pour voir chaque sink avant d'en bloquer un. Le reste de cet article est le mode d'emploi, y compris les schémas par framework pour Angular, React et DOMPurify.

Cet article s'appuie sur [trusted-types-eval, une façon plus sûre d'autoriser eval dans une CSP](/fr/blog/trusted-types-eval-csp), qui couvre spécifiquement le sink eval. Pour les problèmes de script inline et de chaîne-vers-code à côté desquels Trusted Types se situe, voyez [pourquoi vous ne devriez jamais utiliser unsafe-inline dans une CSP](/fr/blog/unsafe-inline-csp) et [unsafe-eval et comment le supprimer](/fr/blog/unsafe-eval-csp).

## Ce contre quoi Trusted Types protège [#ce-contre-quoi-trusted-types-protège]

Le XSS DOM survient quand du code côté client passe du texte contrôlé par l'attaquant dans un sink qui le parse comme du HTML ou l'exécute comme du script. Un cas classique est `element.innerHTML = location.hash`. Les défenses côté serveur ne le voient jamais, parce que l'affectation dangereuse a lieu dans le navigateur, après le chargement de la page, à partir de données que le serveur n'a peut-être jamais touchées.

Trusted Types change la règle au niveau du sink. Quand l'application est active, un sink d'injection n'accepte plus du tout une chaîne. Il accepte un objet `TrustedHTML`, `TrustedScript` ou `TrustedScriptURL`, et le seul moyen d'en fabriquer un est de faire passer une chaîne par une fonction de politique enregistrée que vous avez écrite. Cela vous donne un seul endroit auditable où chaque valeur entrant dans un sink est vérifiée, et fait échouer le motif dangereux bruyamment au lieu de l'exécuter.

## Activer l'application avec require-trusted-types-for [#activer-lapplication-avec-require-trusted-types-for]

Une seule directive active Trusted Types. La directive `require-trusted-types-for` prend la valeur unique `'script'`, qui indique au navigateur d'appliquer Trusted Types au niveau des sinks DOM liés aux scripts :

```http
Content-Security-Policy: require-trusted-types-for 'script'
```

Avec ce header présent, affecter une chaîne brute à `innerHTML` (ou à tout sink couvert) lève une `TypeError` et émet un rapport de violation. Rien d'autre ne fonctionne différemment. Cette directive n'a pas de repli vers `default-src`, elle ne s'applique donc que lorsque vous la définissez explicitement.

## Autoriser vos politiques avec la directive trusted-types [#autoriser-vos-politiques-avec-la-directive-trusted-types]

L'application seule bloquerait aussi votre propre code, parce que votre code écrit lui aussi dans ces sinks. La directive `trusted-types` nomme quelles politiques Trusted Types la page est autorisée à créer. Une politique est un petit objet avec des fonctions `createHTML`, `createScript` ou `createScriptURL` qui contrôlent une chaîne et renvoient la valeur typée.

Listez les noms de politiques que vous comptez enregistrer :

```http
Content-Security-Policy: trusted-types myPolicy
```

Quelques tokens valent la peine d'être connus :

* `'none'` interdit toute création de politique, le réglage le plus strict, utile une fois que vous avez supprimé chaque écriture directe dans un sink.
* `*` autorise n'importe quel nom de politique unique (moins strict, pratique pendant le déploiement).
* `'allow-duplicates'` permet d'enregistrer plusieurs fois le même nom de politique, ce dont certains bundlers et micro-frontends ont besoin.
* `default` est le nom réservé à la politique par défaut. Si vous enregistrez une politique nommée `"default"`, le navigateur exécute automatiquement sa fonction `create*` sur toute chaîne brute passée à un sink, ce qui permet d'adapter Trusted Types à du code que vous ne pouvez pas éditer. Utilisez-le délibérément, car une politique par défaut faible rouvre la surface d'attaque.

Combinez les deux directives en une seule politique, une directive par ligne pour la lisibilité :

```http
Content-Security-Policy:
  require-trusted-types-for 'script';
  trusted-types myPolicy
```

## Enregistrer une politique dans votre code [#enregistrer-une-politique-dans-votre-code]

Une politique est l'endroit où vous mettez la véritable sanitisation. Créez-la une fois, puis routez chaque écriture de sink à travers elle. Voici une politique minimale qui sanitise du HTML avant qu'il ne devienne un `TrustedHTML` :

```javascript
// Register a named policy. The name must be in the trusted-types directive.
const policy = window.trustedTypes.createPolicy("myPolicy", {
  createHTML: (input) => {
    // Do the real sanitization here. Returning input untouched is not safe;
    // the policy is only as strong as the check inside it.
    return sanitize(input);
  },
});

// A plain string is now rejected at the sink.
element.innerHTML = userInput; // throws TypeError under enforcement

// A TrustedHTML from your policy is accepted.
element.innerHTML = policy.createHTML(userInput); // runs
```

La valeur est le point de passage, pas l'affectation. Chaque chaîne qui devient du markup passe par `createHTML`, vous avez donc une seule fonction à relire, tester et durcir, au lieu d'auditer chaque `innerHTML` dans la base de code.

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

Activer l'application sur un site en production cassera tout ce qui écrit une chaîne brute dans un sink couvert, ce qui, sur la plupart des applications, représente beaucoup d'endroits que vous ne connaissez pas encore. Faites-le par étapes et surveillez les rapports avant d'appliquer, la même approche Report-Only d'abord que pour toute modification CSP couverte dans [comment construire une CSP solide, étape par étape](/fr/blog/how-to-build-a-strong-csp).

```mermaid
flowchart LR
  A["Report-Only"] --> B["Voir les violations"]
  B --> C["Ajouter les politiques"]
  C --> D["Appliquer"]
```

Déployez les directives sur le header `Content-Security-Policy-Report-Only`. Le navigateur ne bloque rien ; il envoie un rapport de violation pour chaque écriture de sink que l'application aurait rejetée.

```http
Content-Security-Policy-Report-Only:
  require-trusted-types-for 'script';
  trusted-types myPolicy;
  report-to csp-endpoint
```

Câblez l'endpoint avec le header `Reporting-Endpoints` :

```http
Reporting-Endpoints: csp-endpoint="https://<Endpoint-ID>.report.centralcsp.com"
```

Les violations Trusted Types n'introduisent pas de nouveau type de rapport. Elles arrivent comme des rapports de violation CSP standard, atterrissent donc au même endpoint et se lisent avec les mêmes champs `effectiveDirective`, `sample` et `sourceFile` que tout autre script bloqué. Collectez-les, corrigez chaque sink (routez-le par une politique ou supprimez-le), et ne basculez vers le header `Content-Security-Policy` appliqué qu'une fois le Report-Only silencieux.

CentralCSP ingère ces rapports Report-Only et les regroupe par page et par sink, pour que vous voyiez quelles parties de l'application écrivent encore des chaînes brutes avant d'appliquer. Vous pouvez aussi vérifier les points faibles d'un brouillon de politique avec l'[évaluateur CSP](/tools/csp-evaluator) gratuit avant de le déployer.

## Schémas par framework [#schémas-par-framework]

La plupart des applications n'appellent pas directement les sinks ; un framework le fait pour elles. Le travail Trusted Types porte alors surtout sur la façon dont ce framework obtient sa fonction `create*`.

### Angular [#angular]

[Angular](https://angular.dev/best-practices/security) dispose d'un support Trusted Types intégré. Son `DomSanitizer` passe déjà par une politique Trusted Types, nommée `angular` pour le framework et `angular#bundler` pour la sortie de build, donc une application Angular peut tourner sous application une fois que vous autorisez ces noms de politiques dans la directive. Listez ceux que votre build utilise :

```http
Content-Security-Policy:
  require-trusted-types-for 'script';
  trusted-types angular angular#bundler
```

Angular enregistre `angular` et `angular#bundler` comme noms de politiques de base. Selon votre build, il peut aussi enregistrer `angular#unsafe-bypass`, `angular#unsafe-jit` ou `angular#unsafe-upgrade`, alors surveillez vos rapports Report-Only et autorisez ceux que votre build utilise réellement. Si vous appelez vous-même des sinks hors des API d'Angular, enregistrez votre propre politique supplémentaire et ajoutez son nom à la liste.

### React avec DOMPurify [#react-avec-dompurify]

React échappe le texte par défaut, mais `dangerouslySetInnerHTML` écrit directement dans le DOM, c'est donc le sink à garder. [DOMPurify](https://github.com/cure53/DOMPurify) sanitise du HTML et peut renvoyer directement une valeur Trusted Types avec l'option `RETURN_TRUSTED_TYPE`, ce qui signifie que la sortie sanitisée est déjà un `TrustedHTML` produit par votre politique :

```javascript
import DOMPurify from "dompurify";

// DOMPurify creates a Trusted Types policy named "dompurify" internally.
const clean = DOMPurify.sanitize(dirtyHtml, { RETURN_TRUSTED_TYPE: true });

// clean is a TrustedHTML, accepted by the sink under enforcement.
<div dangerouslySetInnerHTML={{ __html: clean }} />;
```

Autorisez la politique que DOMPurify enregistre (`dompurify`) plus toutes les vôtres :

```http
Content-Security-Policy:
  require-trusted-types-for 'script';
  trusted-types dompurify myPolicy
```

Ce schéma fonctionne pour tout framework qui expose un sink HTML brut : sanitisez avec DOMPurify en mode `RETURN_TRUSTED_TYPE`, passez le résultat typé au sink, et autorisez `dompurify`.

## Le support des navigateurs aujourd'hui [#le-support-des-navigateurs-aujourdhui]

Trusted Types est le plus abouti dans [Chromium](https://www.chromium.org/Home/), qui livre `require-trusted-types-for` et `trusted-types` depuis des années. [Firefox](https://developer.mozilla.org/en-US/docs/Mozilla/Firefox) a ajouté le support plus récemment, et les directives sont récemment devenues disponibles dans les versions actuelles de Chrome, Firefox et Safari. Le support hors de Chromium a historiquement été limité, alors traitez l'application multi-navigateurs généralisée comme récente.

Le comportement se dégrade en toute sécurité. Un navigateur qui n'applique pas Trusted Types ignore les directives et exécute la page comme avant, donc les déployer ne casse pas les clients plus anciens ; vous n'obtenez simplement pas la protection là. Cela permet de l'activer dès maintenant et de gagner la protection partout où le navigateur la prend en charge.

## Foire aux questions [#foire-aux-questions]

### Comment activer Trusted Types ? [#comment-activer-trusted-types-]

Ajoutez `require-trusted-types-for 'script'` à votre CSP pour activer l'application, et ajoutez une directive `trusted-types` listant les noms de politiques que votre code crée. Routez chaque écriture de sink DOM par l'une de ces politiques, et déployez-la d'abord sur le header `Content-Security-Policy-Report-Only` pour attraper chaque sink avant d'en bloquer un.

### Que fait require-trusted-types-for ? [#que-fait-require-trusted-types-for-]

Elle indique au navigateur d'appliquer Trusted Types aux sinks DOM liés aux scripts comme `innerHTML`, `document.write` et `eval`. Sa seule valeur est le token `'script'`. Une fois définie, ces sinks rejettent une chaîne brute et n'acceptent qu'un objet typé produit par l'une de vos politiques enregistrées.

### Qu'est-ce que la politique Trusted Types par défaut ? [#quest-ce-que-la-politique-trusted-types-par-défaut-]

Une politique enregistrée avec le nom réservé `"default"`. Le navigateur exécute automatiquement sa fonction `create*` sur toute chaîne brute passée à un sink, ce qui adapte Trusted Types à du code que vous ne pouvez pas changer. C'est pratique mais cela élargit la surface, alors gardez les contrôles de la politique par défaut stricts.

### Puis-je utiliser Trusted Types avec React ? [#puis-je-utiliser-trusted-types-avec-react-]

Oui. Gardez `dangerouslySetInnerHTML` en sanitisant avec DOMPurify en mode `RETURN_TRUSTED_TYPE`, qui renvoie un `TrustedHTML` que le sink accepte sous application, puis autorisez le nom de politique `dompurify` dans la directive `trusted-types`.

## À retenir [#à-retenir]

Activer Trusted Types tient en deux directives et une habitude : `require-trusted-types-for 'script'` active l'application, `trusted-types` autorise les politiques qui peuvent créer des valeurs typées, et chaque écriture de sink passe par une politique que vous pouvez auditer. Déployez-le en Report-Only, corrigez les sinks que les rapports font remonter, puis appliquez. Les frameworks font le gros du travail : Angular livre ses propres politiques, et DOMPurify remet à React un `TrustedHTML` directement.

Si vous voulez instrumenter le déploiement, [commencez gratuitement avec CentralCSP](/register), pointez-y un header Report-Only, et observez quels sinks ont encore besoin d'une politique avant d'appliquer.

## Sources [#sources]

* [W3C, spécification Trusted Types](https://w3c.github.io/trusted-types/dist/spec/)
* [MDN, API Trusted Types](https://developer.mozilla.org/en-US/docs/Web/API/Trusted_Types_API)
* [Angular, sécurité et Trusted Types](https://angular.dev/best-practices/security)
* [DOMPurify, source et options](https://github.com/cure53/DOMPurify)

## En relation [#en-relation]

* [trusted-types-eval, une façon plus sûre d'autoriser eval dans une CSP](/fr/blog/trusted-types-eval-csp)
* [Pourquoi vous ne devriez jamais utiliser unsafe-inline dans une CSP](/fr/blog/unsafe-inline-csp)
* [unsafe-eval et comment le supprimer](/fr/blog/unsafe-eval-csp)
