FlawOpen

flawopen.com/XSS in JavaScript/DOMPurify and innerHTML

DOMPurify suffit-il à sécuriser innerHTML ?

Guide de référence
Réponse courte

DOMPurify est un puissant sanitizer à liste d’autorisation pour le HTML riche si sa sortie est insérée directement dans un sink HTML sans modification ultérieure. Imaginez un colis contrôlé au quai : si un autre processus le réemballe ou l’achemine par une autre entrée, le contrôle initial ne couvre plus son contenu. Pour du texte brut, utilisez textContent sans interpréter de HTML.

RISQUÉ — une ancienne sortie atteint le sink
// Sanitisation à l’enregistrement avec une ancienne version/politique.
saveToDb(DOMPurify.sanitize(input));

// Le rendu fait ensuite confiance à la valeur enregistrée.
el.innerHTML = fetchedFromDb;
PLUS SÛR — sanitiser pour ce sink HTML
// Si du HTML riche est nécessaire, utilisez la version actuelle
// juste avant l’insertion dans le contexte HTML.
el.innerHTML = DOMPurify.sanitize(untrustedHtml, {
  USE_PROFILES: { html: true },
});

// Pour du texte brut, ne l’interprétez pas comme du HTML.
textNode.textContent = untrustedText;

Pourquoi une sanitisation unique à l’enregistrement est moins robuste

Sanitiser à l’enregistrement n’est pas forcément dangereux, mais crée une frontière de données anciennes : un rendu peut faire confiance à une sortie antérieure après une correction du sanitizer, un changement de politique ou un chemin qui a omis l’étape. Re-sanitisez au rendu avec la version actuelle et la politique du sink précis. Ne modifiez pas le balisage nettoyé et ne le faites pas passer par une autre bibliothèque avant insertion : le post-traitement peut annuler la sanitisation.

La configuration et le contexte de sortie comptent

La configuration par défaut de DOMPurify autorise HTML, SVG et MathML. Si seul le HTML est nécessaire, limitez le profil avec USE_PROFILES: { html: true }. N’élargissez pas les balises ou attributs sans revue. DOMPurify ne sanitize pas le CSS et n’empêche pas toutes les requêtes externes ; gardez la sortie dans le contexte HTML, sans la réutiliser en JavaScript, attribut, XML, SVG ou CSS.

Trusted Types et rendu côté serveur

Quand c’est pris en charge, imposez Trusted Types avec une Content Security Policy afin de rejeter les chaînes affectées aux sinks HTML sans politique approuvée. DOMPurify peut produire TrustedHTML ; cela réduit les affectations accidentelles, mais ne corrige ni une configuration risquée ni le post-traitement. Côté serveur, DOMPurify dépend d’un DOM : maintenez jsdom à jour et ne l’associez pas à happy-dom pour une sanitisation sensible à la sécurité.

Liste de contrôle de production

Rechercher les sinks HTML

rg -n -g '*.{js,ts,jsx,tsx}' '(innerHTML|outerHTML|insertAdjacentHTML|document\.write|dangerouslySetInnerHTML)' .
Pour chaque résultat, suivez les données non fiables jusqu’au sink, vérifiez que la sanitisation précède immédiatement l’insertion et qu’aucun code ultérieur ne modifie le balisage.

Sources et références

À voir aussi Cross-Site Scripting (XSS, CWE-79) : fonctionnement et prévention dans chaque langage — flawopen.com Markdown protège-t-il contre les XSS ? Svelte protège-t-il du XSS par défaut ? Un téléversement SVG présente-t-il un risque XSS ? Risque XSS de Vue v-html WKWebView : HTML non fiable, sûr ? XSS réfléchi, stocké et DOM : quelles différences ?