Start · Sprachen · JavaScript · Referenz · TrustedScriptURL

TrustedScriptURL

Schnittstelle

Stellt eine geprüfte Zeichenkette dar, die an Senken wie <code>script.src</code> übergeben werden darf, die sie als URL eines externen Skripts laden.

seit JavaScript Chromium 83+, Safari 26+, Firefox 145+ (Baseline 2 Kategorie: webapi

Signatur

interface TrustedScriptURL

Beschreibung

TrustedScriptURL gehört zur Trusted Types API. Ein Objekt dieses Typs kapselt eine URL, die von einer Richtlinie (TrustedTypePolicy) geprüft wurde und deshalb an Stellen verwendet werden darf, an denen der Browser sie als Adresse eines ausführbaren Skripts lädt. Typische Senken sind HTMLScriptElement.src, Worker, SharedWorker, importScripts(), navigator.serviceWorker.register() sowie setAttribute('src', …) auf <script>-Elementen.

Einen eigenen Konstruktor gibt es nicht. Instanzen erzeugt man ausschließlich über policy.createScriptURL(input), wobei policy mit trustedTypes.createPolicy(name, { createScriptURL }) angelegt wird. In der Funktion createScriptURL steht die eigentliche Sicherheitslogik, zum Beispiel eine Positivliste erlaubter Ursprünge.

Ist per CSP require-trusted-types-for 'script' gesetzt, lehnt der Browser einfache Zeichenketten an diesen Senken ab und wirft einen TypeError. So wird Code, der Skript-URLs zuweist, auf wenige, gut prüfbare Richtlinien reduziert, und DOM-basiertes XSS lässt sich wirksam eindämmen.

Das Interface stellt nur zwei Methoden bereit: toString() und toJSON(). Beide geben die gekapselte URL als Zeichenkette zurück. Ob ein Wert vertrauenswürdig ist, prüft man mit trustedTypes.isScriptURL(value).

Rückgabewert

Typ
TrustedScriptURL
Beschreibung
Instanzen entstehen nur über TrustedTypePolicy.createScriptURL(). Mit toString() bzw. toJSON() erhält man die URL als string.

Beispiele

Richtlinie mit Positivliste anlegen und Skript laden

// Nur Skripte vom eigenen Ursprung und einem festgelegten CDN zulassen
const ERLAUBTE_URSPRUENGE = [location.origin, 'https://cdn.example.com'];

const scriptPolicy = trustedTypes.createPolicy('script-loader', {
  createScriptURL: (input) => {
    const url = new URL(input, location.href);
    if (!ERLAUBTE_URSPRUENGE.includes(url.origin)) {
      throw new TypeError(`Ursprung nicht erlaubt: ${url.origin}`);
    }
    return url.href;
  },
});

const trustedUrl = scriptPolicy.createScriptURL('https://cdn.example.com/lib.js');
console.log(trustedUrl instanceof TrustedScriptURL);

const script = document.createElement('script');
script.src = trustedUrl; // wird auch unter require-trusted-types-for akzeptiert
document.head.append(script);
true

Web Worker mit TrustedScriptURL starten

const workerPolicy = trustedTypes.createPolicy('worker-policy', {
  createScriptURL: (input) => {
    if (!input.startsWith('/workers/')) {
      throw new TypeError('Nur Worker aus /workers/ erlaubt');
    }
    return input;
  },
});

const worker = new Worker(workerPolicy.createScriptURL('/workers/rechner.js'));
worker.onmessage = (event) => console.log('Ergebnis:', event.data);
worker.postMessage({ a: 2, b: 3 });
Ergebnis: 5 (abhängig vom Worker-Code)

Typ prüfen und in einen String umwandeln

const policy = trustedTypes.createPolicy('demo', {
  createScriptURL: (s) => s,
});

const trusted = policy.createScriptURL('/js/app.js');

console.log(trustedTypes.isScriptURL(trusted));     // echter TrustedScriptURL
console.log(trustedTypes.isScriptURL('/js/app.js')); // einfacher String
console.log(trusted.toString());
console.log(JSON.stringify({ src: trusted }));
true false /js/app.js {"src":"/js/app.js"}

Rückfall für Browser ohne Trusted Types

const loadScript = (src) => {
  const script = document.createElement('script');
  if (window.trustedTypes?.createPolicy) {
    const policy = trustedTypes.createPolicy('fallback-loader', {
      createScriptURL: (u) => {
        const url = new URL(u, location.href);
        if (url.origin !== location.origin) throw new TypeError('Fremder Ursprung');
        return url.href;
      },
    });
    script.src = policy.createScriptURL(src);
  } else {
    script.src = src; // ältere Browser: normale Zuweisung
  }
  document.head.append(script);
};

loadScript('/js/analytics.js');

// Wichtig · Fallstricke

  • Kein Konstruktor: new TrustedScriptURL() wirft einen TypeError. Instanzen entstehen nur über createScriptURL() einer Richtlinie.
  • Sicherheit steht und fällt mit der Richtlinie: Eine Richtlinie wie createScriptURL: s => s hebelt den Schutz vollständig aus. Prüfen Sie Ursprung und Pfad mit new URL(), nicht mit einfachen String-Vergleichen wie startsWith('https://cdn'). Diese lassen sich etwa mit https://cdn.evil.com umgehen. Lehnen Sie javascript:-, data:- und blob:-URLs ab, wenn sie nicht ausdrücklich gebraucht werden.
  • CSP: Durchgesetzt wird der Schutz erst mit dem Header Content-Security-Policy: require-trusted-types-for 'script'. Mit trusted-types name1 name2 legen Sie fest, welche Richtliniennamen angelegt werden dürfen. Zum Testen eignet sich zunächst Content-Security-Policy-Report-Only.
  • Falscher Typ: Ein TrustedHTML oder TrustedScript wird an einer Skript-URL-Senke nicht akzeptiert. Es muss genau TrustedScriptURL sein.
  • Default-Richtlinie: Eine Richtlinie mit dem Namen 'default' wird automatisch aufgerufen, wenn ein einfacher String an eine Senke übergeben wird. Das hilft beim schrittweisen Umstellen, ist aber ein zentraler Sicherheitspunkt.
  • Browser-Unterstützung: Seit langem in Chromium-Browsern (Chrome, Edge, Opera), inzwischen auch in Safari 26 und Firefox 145. Für ältere Browser gibt es das Polyfill trusted-types (w3c/trusted-types). Sonst per window.trustedTypes?.createPolicy auf Verfügbarkeit prüfen. Nur in sicheren Kontexten (HTTPS) und auch in Workern verfügbar.