Trusted Types ist eine Sicherheitsfunktion, die DOM-basiertes Cross-Site-Scripting (DOM XSS) verhindert. Dazu müssen Daten, die an „gefährliche“ Browser-APIs (sogenannte Senken) übergeben werden, zuerst in einen bestimmten Typ wie TrustedHTML konvertiert werden.
Standardmäßig akzeptieren viele DOM APIs (z. B. innerHTML oder document.write) Rohstrings. Wenn ein String ein schädliches Script aus einer nicht vertrauenswürdigen Quelle enthält, kann es ausgeführt werden. Trusted Types ändern dieses Verhalten: Sobald sie über die CSP aktiviert sind, akzeptieren diese Senken nur noch TrustedHTML-Objekte, die von autorisierten Richtlinien erstellt wurden.
Wichtige Implementierungsdetails
So verwenden Sie Trusted Types:
- Definieren Sie eine Sicherheitsrichtlinie, die festlegt, wie Strings bereinigt oder transformiert werden sollen.
- Verwenden Sie diese Richtlinie, um Trusted Type-Objekte aus Rohstrings zu erstellen.
- Verwenden Sie die Trusted Type-Objekte, wenn Sie in DOM-Senken schreiben.
- Erzwingen Sie Trusted Types mithilfe einer Content Security Policy (CSP).
1. Richtlinie erstellen
Eine Richtlinie ist eine Reihe von Regeln zum Bereinigen von Inhalten. Sie erstellen es mit trustedTypes.createPolicy() und delegieren es in der Regel an eine Sanitizer-Bibliothek wie DOMPurify oder die HTML-Escaping-Regeln Ihrer Anwendung:
import DOMPurify from 'dompurify';
const myPolicy = trustedTypes.createPolicy('sanitize-html', {
createHTML: (input) =>
// Return a sanitized string; createPolicy() wraps it in a TrustedHTML object.
// Example using DOMPurify:
DOMPurify.sanitize(input, { RETURN_TRUSTED_TYPE: false }),
});
// Example using HTML escaping (for environments without third-party sanitizers):
const escapePolicy = trustedTypes.createPolicy('escape-html', {
createHTML: (input) =>
String(input)
.replaceAll('&', '&')
.replaceAll('<', '<')
.replaceAll('>', '>')
.replaceAll('"', '"')
.replaceAll("'", '''),
});
2. Richtlinie verwenden
Anstatt einen String direkt an eine Senke zu übergeben, rufen Sie die Erstellungsmethode der Richtlinie auf.
const untrustedInput = '<p>Hello, <strong>world</strong>!</p><img src="x" onerror="alert(1)">';
// In an enforced environment, this would throw a TypeError:
// element.innerHTML = untrustedInput;
// This returns a TrustedHTML object with unsafe elements and attributes removed:
const cleanHTML = myPolicy.createHTML(untrustedInput);
// Result: "<p>Hello, <strong>world</strong>!</p><img src=\"x\">"
3. Senken auf die Verwendung von Trusted Types umstellen
Aktualisieren Sie jede Instanz, in der Sie in eine Senke schreiben, um sie zuerst in ein Trusted Type-Objekt zu konvertieren. Um herauszufinden, wo Code aktualisiert werden muss, können Sie eine temporäre default-Richtlinie definieren, die protokolliert, wenn eine Senke mit einem String anstelle eines TrustedType beschrieben wird.
trustedTypes.createPolicy("default", {
createHTML(value) {
console.warn("String passed instead of Trusted Type.");
return DOMPurify.sanitize(value, { RETURN_TRUSTED_TYPE: false });
},
});
Zu den gängigen Senken, die vertrauenswürdige Typen unterstützen, gehören:
- HTML:
element.innerHTML,element.outerHTML,document.write(),element.setHTMLUnsafe(),Document.parseHTMLUnsafe() - Skript:
<script>-Textinhalt,eval() - ScriptURL:
<script src>,Worker(),SharedWorker()
// Assign the TrustedHTML object.
element.innerHTML = cleanHTML;
Beachten Sie, dass für die „sicheren“ HTML-Sanitizing-Methoden (element.setHTML() und Document.parseHTML(), die unter Nicht vertrauenswürdiges HTML bereinigen behandelt werden) keine Trusted Types-Richtlinie erforderlich ist, da sie potenzielle XSS-Angriffe immer nativ bereinigen.
4. Vertrauenswürdige Typen mit CSP erzwingen
Trusted Types sollten schrittweise eingeführt werden, um zu vermeiden, dass Ihre Anwendung nicht mehr funktioniert. Die vollständige Erzwingung bietet zwar den stärksten Schutz, birgt aber das Risiko, dass die Website nicht mehr funktioniert, wenn nicht alle Sink-Schreibvorgänge migriert wurden.
Vorbereitung
- Framework-Kooperation: Wenn das Framework Ihrer Anwendung (oder eine Drittanbieterbibliothek, die in DOM-Senken schreibt) keine
TrustedHTML- oderTrustedScript-Werte erzeugt, können Sie Trusted Types nicht erzwingen, ohne den Code zu beschädigen. Prüfen Sie die Framework-Unterstützung, bevor Sie mit dem Roll-out beginnen. - Senken-Refaktorierung: Achten Sie darauf, dass Sie gefährliche Senken identifiziert und refaktoriert haben, um Ihre Trusted Types-Richtlinien zu verwenden.
Roll‑out-Strategie
Nur Berichterstellung: Führen Sie die Funktion zuerst mit dem Header
Content-Security-Policy-Report-Onlyein. Dadurch werden Verstöße an Ihrem Berichterstellungsendpunkt protokolliert, ohne dass die Schreibvorgänge tatsächlich blockiert werden.Content-Security-Policy-Report-Only: require-trusted-types-for 'script';Durchsetzung: Sobald Sie Ihre Richtlinien integriert haben und keine Verstöße mehr gemeldet werden, können Sie die Richtlinien vollständig durchsetzen.
Content-Security-Policy: require-trusted-types-for 'script';
Sie können auch einschränken, welche Richtlinien erstellt werden dürfen. Listen Sie dazu die Richtliniennamen auf, z. B. sanitize-html oder escape-html. Fügen Sie dompurify hinzu, wenn Ihre Richtlinie an DOMPurify.sanitize() delegiert wird (wodurch intern eine dompurify-Richtlinie erstellt wird). Fügen Sie default hinzu, wenn Sie während der Migration eine Standardrichtlinie registrieren:
Content-Security-Policy: require-trusted-types-for 'script'; trusted-types sanitize-html escape-html dompurify;
Mit dieser CSP wird bei allen Schreibvorgängen in eine Senke, die keine vertrauenswürdigen Typen verwenden, ein Fehler ausgegeben. Außerdem wird ein Fehler ausgegeben, wenn versucht wird, eine Trusted Type-Richtlinie mit einem Namen zu erstellen, der nicht in trusted-types aufgeführt ist.
Sie können diese CSP auch als <meta>-Tag im <head>-Element Ihres Dokuments festlegen. Das ist jedoch möglicherweise weniger sicher.
<!-- First child of `<head>`, as earlier tags will not enforce this CSP. -->
<meta
http-equiv="Content-Security-Policy"
content="require-trusted-types-for 'script'; trusted-types sanitize-html escape-html dompurify;"
/>
Fallback-Strategien
Für Browser, die Trusted Types noch nicht unterstützen, können Sie ein minimales „Tinyfill“ verwenden, um sicherzustellen, dass Ihr Code nicht fehlerhaft ist, und gleichzeitig eine Bereinigung zu ermöglichen.
if (!window.trustedTypes) {
window.trustedTypes = {
createPolicy: (name, rules) => rules,
};
}
So können Sie Ihren Code schon heute mit dem Trusted Types-Muster schreiben. Unterstützende Browser erzwingen die Typen, während ältere Browser die Bereinigungslogik weiterhin über die Mock-Richtlinie ausführen.
Wenn ein Browser Trusted Types nicht unterstützt, behandelt er die TrustedHTML-Objekte einfach als Strings (wenn Tinyfill verwendet wird) oder führt die Überprüfung auf der Senkenebene nicht durch.