FlawOpen

flawopen.com/XSS in JavaScript/DOMPurify and innerHTML

Reicht DOMPurify, um innerHTML sicher zu machen?

Referenzleitfaden
Kurzantwort

DOMPurify ist ein starker Allowlist-Sanitizer für Rich-HTML, wenn die Ausgabe ohne spätere Änderung direkt in einen HTML-Sink gelangt. Wie bei einem Paket am Wareneingang gilt: Wird es danach umgepackt oder über einen anderen Eingang eingeschleust, deckt die erste Prüfung den Inhalt nicht mehr ab. Für normalen Text verwenden Sie textContent statt HTML zu parsen.

WEITERHIN RISKANT — alter Output erreicht den Sink
// Beim Speichern mit alter Version/Policy sanitisiert.
saveToDb(DOMPurify.sanitize(input));

// Später wird dem gespeicherten Wert ungeprüft vertraut.
el.innerHTML = fetchedFromDb;
SICHERER — für diesen HTML-Sink sanitizen
// Wenn Rich-HTML nötig ist, aktuelle Version verwenden
// direkt vor dem Einfügen in den HTML-Kontext.
el.innerHTML = DOMPurify.sanitize(untrustedHtml, {
  USE_PROFILES: { html: true },
});

// Reiner Text wird nicht als HTML geparst.
textNode.textContent = untrustedText;

Warum einmaliges Sanitizing beim Speichern schwächer ist

Sanitizing beim Speichern ist nicht automatisch unsicher, schafft aber eine Grenze für veraltete Daten: Ein Renderer kann alten Output nach einem Sanitizer-Fix, einer Policy-Änderung oder einem übersprungenen Pfad weiter vertrauen. Sanitizen Sie beim Rendern erneut mit der aktuellen Version und der Policy des konkreten Sinks. Ändern Sie das bereinigte Markup nicht und geben Sie es vor dem Einfügen nicht an eine andere Bibliothek weiter; Nachbearbeitung kann den Sanitizer-Effekt aufheben.

Konfiguration und Ausgabekontext zählen

DOMPurify erlaubt standardmäßig HTML, SVG und MathML. Wenn nur HTML nötig ist, schränken Sie das Profil mit USE_PROFILES: { html: true } ein. Erweitern Sie Tags oder Attribute nur nach Prüfung. DOMPurify ist kein CSS-Sanitizer und verhindert nicht alle externen Anfragen; verwenden Sie die Ausgabe nur im HTML-Kontext, nicht in JavaScript, Attributen, XML, SVG oder CSS.

Trusted Types und serverseitiges Rendering

Erzwingen Sie, sofern unterstützt, Trusted Types über eine Content Security Policy, damit Strings an HTML-Sinks ohne freigegebene Policy abgewiesen werden. DOMPurify kann TrustedHTML liefern; das verhindert versehentliche Sink-Nutzung, behebt aber weder unsichere Konfiguration noch Nachbearbeitung. Serverseitig benötigt DOMPurify eine DOM-Implementierung: Halten Sie jsdom aktuell und kombinieren Sie es für sicherheitskritisches Sanitizing nicht mit happy-dom.

Produktions-Checkliste

HTML-Sinks im Code suchen

rg -n -g '*.{js,ts,jsx,tsx}' '(innerHTML|outerHTML|insertAdjacentHTML|document\.write|dangerouslySetInnerHTML)' .
Verfolgen Sie bei jedem Treffer nicht vertrauenswürdige Daten bis zum Sink, prüfen Sie die Sanitization direkt vor dem Einfügen und stellen Sie sicher, dass späterer Code das Markup nicht ändert.

Quellen und Referenzen

Siehe auch Cross-Site-Scripting (XSS, CWE-79): Funktionsweise und Schutz in jeder Sprache — flawopen.com Ist Markdown-Rendering vor XSS sicher? Schützt Svelte standardmäßig vor XSS? Ist ein SVG-Upload ein XSS-Risiko? XSS-Risiko durch Vue v-html WKWebView: Nicht vertrauenswürdiges HTML? Reflected, Stored und DOM-basiertes XSS: Wo liegt der Unterschied?