Wenn Sie Skripts, Stylesheets, Schriftarten oder Bilder von Drittanbieter-CDNs oder externen Quellen laden, sollten Sie deren kryptografische Integrität mit Subresource Integrity (integrity in HTML und integrity() in CSS url()) überprüfen, die ursprungsübergreifende Verarbeitung von Anmeldedaten (crossorigin und cross-origin()) konfigurieren und ausgehende Referer-Header (referrerpolicy und referrer-policy()) einschränken. Informationen zu Content Security Policies auf Dokumentebene und Zulassungslisten für ausgehende Verbindungen finden Sie unter Web Security und Ausgehende Netzwerkverbindungen mit Zulassungslisten für Verbindungen einschränken.
1. Kryptografische Integritäts-Digests für unveränderliche Assets generieren
Subresource Integrity (SRI) sorgt dafür, dass der Browser ein externes Asset nur dann ausführt oder rendert, wenn seine Bytes mit dem von Ihrer Anwendung deklarierten kryptografischen Hash übereinstimmen.
- Prüfsummen während des Build- oder Release-Prozesses berechnen, niemals aus nicht vertrauenswürdigen Live-Antworten: Generieren Sie Integritäts-Hashes während des Build- oder Release-Schritts aus bekannten, fehlerfreien lokalen Asset-Bytes (oder kopieren Sie die offizielle Prüfsumme, die vom Paketautor veröffentlicht wurde) und codieren Sie sie fest in Ihren HTML-, CSS- oder JavaScript-Code. Rufen Sie niemals zur Laufzeit eine Drittanbieter-URL im Browser ab, um den eigenen
integrity-Hash zu berechnen. Dadurch wird allen vom Remote-Server zurückgegebenen Bytes vertraut und SRI wird umgangen. - Standardmäßig
sha384-verwenden: Integritätsmetadaten als<algorithm>-<base64-digest>mitsha384-(empfohlener Standard),sha512-odersha256-formatieren. - Externe Unterressourcen an unveränderliche, versionierte URLs anpinnen: Verweisen Sie immer auf Drittanbieter-Assets mit unveränderlichen, versionsgebundenen oder inhaltsadressierten URLs (z. B.
https://cdn.example.com/ui@2.4.0/app.min.js) anstatt mit veränderlichen, dynamischen URLs (latest/app.min.js). Letztere setzen Ihre Website unbemerkten Änderungen in der Lieferkette aus und beeinträchtigen die SRI, sobald die Remote-Datei aktualisiert wird. Wenn Sie ein veränderliches Drittanbieter-Script laden müssen, das direkt aktualisiert wird (z. B. ein Analyse-Tag eines Anbieters), lassen Sieintegrityfür diese URL weg und schränken Sie sie stattdessen mit der Content Security Policy (strict-dynamic/Nonces) oder iFrame-Sandboxing ein. - Trennen Sie mehrere Digests durch Leerzeichen, wenn ein Endpunkt mehrere gültige Nutzlasten bereitstellen kann: Alle Browser, die SRI unterstützen, implementieren
sha256-,sha384-undsha512-. Wenn eine URL legitimerweise eine von mehreren bekannten, fehlerfreien Nutzlasten zurückgeben kann (z. B. während eines A/B-Tests, eines gestaffelten CDN-Rollouts oder eines Builds mit Inhaltsverhandlung), listen Sie mehrere Digests desselben Algorithmus durch Leerzeichen getrennt auf (z. B.integrity="sha384-variantA... sha384-variantB..."). Der Browser akzeptiert die Antwort, wenn sie mit einem der aufgeführten Digests des stärksten vorhandenen Algorithmus übereinstimmt. - Ursprungsübergreifende Unterressourcen mit CORS-Headern bereitstellen: Browser können die Integrität einer ursprungsübergreifenden Antwort nur überprüfen, wenn sie CORS-lesbar ist (
Access-Control-Allow-Origin: *für anonyme Anfragen oder der genaue anfragende Ursprung mitAccess-Control-Allow-Credentials: truefür Anfragen mit Anmeldedaten).
# Generate a sha384- SRI hash at build time from a known-good local file
printf "sha384-%s\n" "$(openssl dgst -sha384 -binary app.min.js | openssl base64 -A)"
// Build-time / tooling helper (Node.js 19+, Deno, Bun) to compute an SRI string from known-good local bytes
export async function computeIntegrityMetadata(bytes) {
const rawBytes =
typeof bytes === 'string' ? new TextEncoder().encode(bytes) : bytes;
const digestBuffer = await crypto.subtle.digest('SHA-384', rawBytes);
const binary = Array.from(new Uint8Array(digestBuffer), (b) =>
String.fromCharCode(b),
).join('');
return `sha384-${btoa(binary)}`;
}
2. Sichere HTML-Skripts, Stylesheets und Preloads
Legen Sie einen HTTP-Antwortheader Referrer-Policy: strict-origin-when-cross-origin auf Dokumentebene fest (oder fügen Sie <meta name="referrer" content="strict-origin-when-cross-origin"> in <head> ein) als Standard-Baseline, damit alle Unterressourcen oder CSS-url(), die einen Referrer-Modifikator pro Anfrage weglassen, weiterhin sensible Pfad- und Suchparameter bei ursprungsübergreifenden Anfragen entfernen.
Legen Sie dann für die externen Elemente <script>, <link rel="stylesheet">, <link rel="preload"> und <link rel="modulepreload"> immer integrity, crossorigin und referrerpolicy zusammen fest:
integrity="sha384-...": Blockiert die Ausführung oder Anwendung der Ressource, wenn die Antwortbytes nicht mit dem erwarteten Digest übereinstimmen. Bei einer blockierten<link rel="stylesheet">bleibtlinkElement.sheetaufnullund einerror-Ereignis wird ausgelöst.crossorigin="anonymous"(empfohlener Standardwert für öffentliche CDN-Assets) odercrossorigin="use-credentials": Erforderlich, wennintegrityfür eine ursprungsübergreifende Ressource festgelegt ist. Wenn Siecrossoriginweglassen, ruft der Browser die Ressource imno-cors-Modus ab (was zu einer intransparenten Antwort führt, die nicht per Hash-Wert überprüft werden kann) und blockiert die Ressource.referrerpolicy="no-referrer"(empfohlener Standard für CDNs von Drittanbietern) oderreferrerpolicy="strict-origin-when-cross-origin": Überschreibt die Referrer-Richtlinie des Dokuments, um zu verhindern, dass Ursprungs- oder Pfadinformationen im AnfrageheaderRefereran den Drittanbieter-Host weitergegeben werden.
<!-- Document-level baseline referrer policy in <head> (or via Referrer-Policy HTTP header) -->
<meta name="referrer" content="strict-origin-when-cross-origin" />
<!-- External stylesheet with SRI, anonymous CORS, and no referrer -->
<link
rel="stylesheet"
href="https://cdn.example.com/ui@2.4.0/styles.css"
integrity="sha384-bs0EksOYBbU/g0IAHMXbSyH1Mgw83GKn+EZlSI+VE+zVchXmSbLwhVLrPzsOWnc5"
crossorigin="anonymous"
referrerpolicy="no-referrer"
/>
<!-- External script with SRI, anonymous CORS, and no referrer -->
<script
src="https://cdn.example.com/ui@2.4.0/bundle.min.js"
integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
crossorigin="anonymous"
referrerpolicy="no-referrer"
></script>
Wenn Sie externe Unterressourcen programmatisch mit fetch() abrufen, übergeben Sie die entsprechenden Optionen integrity, mode, credentials und referrerPolicy. Bei einer Abweichung des Digests wird das Promise mit TypeError abgelehnt:
const response = await fetch('https://cdn.example.com/ui@2.4.0/manifest.json', {
integrity: 'sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC',
mode: 'cors',
credentials: 'omit',
referrerPolicy: 'no-referrer',
});
3. CSS-Bilder, ‑Schriftarten und importierte Stylesheets mit url()-Modifikatoren sichern
Mit den CSS-url()-Anfragemodifikatoren (cross-origin(), referrer-policy() und integrity()) können Sie den Abrufmodus, den Referrer-Header und die Subresource Integrity-Prüfung von über CSS geladenen Ressourcen direkt über CSS steuern. Dazu gehören auch die Regeln background-image, content, mask-image, border-image-source, filter, @font-face, src und @import:
| Modifikatorfunktion | Argumentsyntax und zulässige Werte | Zweck |
|---|---|---|
cross-origin(<ident>) |
Keyword ohne Anführungszeichen: anonymous (empfohlener Standardwert) oder use-credentials |
Ruft die CSS-Ressource mithilfe von CORS ab und steuert, ob Anmeldedaten gesendet werden. Fügen Sie sie immer zusammen mit integrity() in ursprungsübergreifenden CSS-Ressourcen ein. |
referrer-policy(<ident>) |
Keyword ohne Anführungszeichen: no-referrer (empfohlener Standardwert für Drittanbieter-Assets), strict-origin-when-cross-origin, origin, same-origin, strict-origin, origin-when-cross-origin, no-referrer-when-downgrade oder unsafe-url |
Überschreibt die Referrer-Richtlinie des Dokuments für diese spezifische CSS-Anfrage. |
integrity("<string>") |
String in Anführungszeichen: "sha384-<base64>" (oder durch Leerzeichen getrennte Digests "sha384-... sha384-...") |
Prüft die abgerufene CSS-Ressource vor dem Rendern oder Anwenden anhand des erwarteten kryptografischen Digests. |
Beachten Sie beim Erstellen von url()-Modifikatoren die folgenden CSS-Syntax- und Sicherheitsregeln:
- Setzen Sie den URL-String in
url("...")in Anführungszeichen: Anfragemodifikatoren sind nur gültig, wenn die URL inurl(...)ein<string>in Anführungszeichen ist. URLs ohne Anführungszeichen können keine Modifikatoren verwenden. - Geben Sie jeden Modifikatortyp höchstens einmal pro
url()an: Sie könnencross-origin(),referrer-policy()undintegrity()in beliebiger Reihenfolge innerhalb vonurl("..." ...)kombinieren. Es ist jedoch nicht zulässig, denselben Modifikatortyp zweimal zu wiederholen (z. B. zweiintegrity()-Modifikatoren). Wenn Sie mehrere Hashes angeben möchten, trennen Sie sie innerhalb eines einzelnenintegrity("sha384-... sha384-...")-Strings durch Leerzeichen. - Ursprungsübergreifende
integrity()immer mitcross-origin(anonymous)kombinieren: Während@font-face,srcundmask-imagestandardmäßig im anonymencors-Modus abgerufen werden, werdenbackground-image,content,border-image-sourceund@importstandardmäßig imno-cors-Modus abgerufen (was zu einer intransparenten Antwort führt, die nicht per Hash-Wert überprüft werden kann). Externe SVG-filterwerden standardmäßig imsame-origin-Modus abgerufen (was ursprungsübergreifende URLs direkt blockiert). Wenn Siecross-origin(anonymous)(odercross-origin(use-credentials)) einfügen, wird eine konsistente CORS-Überprüfung für alle CSS-Properties sichergestellt. - Modifikatoren in
url("...")in@import- und@font-face-Regeln platzieren: Behalten Siecross-origin(),referrer-policy()undintegrity()inurl("..." ...)bei, während Sie Schriftdeskriptoren wieformat("woff2")undtech(...)außerhalb vonurl(...)beibehalten.
@import url(
"https://cdn.example.com/theme@1.2.0/tokens.css"
cross-origin(anonymous)
referrer-policy(no-referrer)
integrity("sha384-bs0EksOYBbU/g0IAHMXbSyH1Mgw83GKn+EZlSI+VE+zVchXmSbLwhVLrPzsOWnc5")
);
@font-face {
font-family: "BrandSans";
src: url(
"https://cdn.example.com/fonts@1.0.0/brand-sans.woff2"
cross-origin(anonymous)
referrer-policy(no-referrer)
integrity("sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC")
) format("woff2");
font-display: swap;
}
.verified-graphic {
background-image: url(
"https://cdn.example.com/media@1.0.0/badge.svg"
cross-origin(anonymous)
referrer-policy(no-referrer)
integrity("sha384-Iw/0p59dP96nGTzHvf2XIfqcBwBW7RM6JfOij8uZxyg5azfNaOOUW8SQy6H/hU91")
);
}
Fallback-Strategien
Wenn Ihr Baseline-Ziel noch keine CSS-url()-Anfragemodifikatoren (cross-origin(), referrer-policy() oder integrity()) unterstützt, kombinieren Sie Richtlinien auf Dokumentebene mit kaskadierenden CSS-Deklarationen, damit Unterressourcen funktionsfähig und geschützt bleiben:
- HTML-
<link rel="stylesheet">gegenüber CSS-@importbevorzugen, wenn browserübergreifende SRI erforderlich ist: Dasubresource-integrityundreferrer-policyfür<link rel="stylesheet">in allen Browsern weitgehend verfügbar sind, sollten Sie externe Stylesheets mit<link rel="stylesheet" href="..." integrity="sha384-..." crossorigin="anonymous" referrerpolicy="no-referrer">anstelle von@importladen, wenn die Integritätsprüfung in jedem Browser erzwungen werden muss. - Auf den Header
Referrer-Policyoder das Element<meta name="referrer">auf Dokumentebene aus Schritt 2 verlassen: In Browsern, diereferrer-policy()in CSS-url()nicht unterstützen, werden durch den HeaderReferrer-Policy: strict-origin-when-cross-originoder das Element<meta name="referrer" content="strict-origin-when-cross-origin">auf Dokumentebene automatisch vertrauliche Pfad- und Suchparameter bei ursprungsübergreifenden CSS-Anfragen entfernt. Separate CSS-Deklarationen für die progressive Verbesserung kaskadieren: Browser, die einen Modifikator in
url("..." ...)nicht erkennen, verwerfen die gesamte Deklaration beim Parsen des CSS. Deklarieren Sie zuerst ein einfachesurl("..."), gefolgt von einercross-origin()- undreferrer-policy()-Deklaration (für Browser, die diese beiden Modifikatoren, aber nichtintegrity()unterstützen), gefolgt von der vollständigen Deklaration einschließlichintegrity("sha384-..."):- Fügen Sie niemals eine nicht verifizierte
url()in dieselbe kommagetrennte@font-face-src-Liste ein: Wenn Siesrc: url("font.woff2" cross-origin(anonymous) integrity("sha384-...")), url("font.woff2");in einem einzelnensrc-Deskriptor angeben, wird die Subresource Integrity zur Laufzeit umgangen. Wenn ein CDN eine manipulierte Schriftart bereitstellt, die dieintegrity()-Prüfung nicht besteht, behandelt der Browser dies als Ladefehler und greift automatisch auf die zweite kommagetrennteurl("font.woff2")zurück. Wenn Sie separatesrc:-Deklarationen verwenden, überschreiben unterstützende Browser die nicht verifizierte Deklaration beim Parsen des CSS und blockieren manipulierte Schriftarten zur Laufzeit.
@font-face { font-family: "BrandSans"; /* 1. Parse-time fallback for browsers without url() modifier support */ src: url("https://cdn.example.com/fonts@1.0.0/brand-sans.woff2") format("woff2"); /* 2. Parse-time fallback for browsers supporting cross-origin() and referrer-policy() */ src: url( "https://cdn.example.com/fonts@1.0.0/brand-sans.woff2" cross-origin(anonymous) referrer-policy(no-referrer) ) format("woff2"); /* 3. Full protection in browsers supporting cross-origin(), referrer-policy(), and integrity() */ src: url( "https://cdn.example.com/fonts@1.0.0/brand-sans.woff2" cross-origin(anonymous) referrer-policy(no-referrer) integrity("sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC") ) format("woff2"); font-display: swap; } .verified-graphic { background-image: url("https://cdn.example.com/media@1.0.0/badge.svg"); background-image: url( "https://cdn.example.com/media@1.0.0/badge.svg" cross-origin(anonymous) referrer-policy(no-referrer) ); background-image: url( "https://cdn.example.com/media@1.0.0/badge.svg" cross-origin(anonymous) referrer-policy(no-referrer) integrity("sha384-Iw/0p59dP96nGTzHvf2XIfqcBwBW7RM6JfOij8uZxyg5azfNaOOUW8SQy6H/hU91") ); }- Fügen Sie niemals eine nicht verifizierte
Feature-Erkennung für die Unterstützung des CSS-Modifikators
url()in JavaScript mitCSS.supports():
export function getCssUrlModifierSupport() {
const supportsCrossOriginAndReferrer =
typeof CSS !== 'undefined' &&
typeof CSS.supports === 'function' &&
CSS.supports(
'background-image',
'url("https://example.com/a.svg" cross-origin(anonymous) referrer-policy(no-referrer))',
);
const supportsUrlIntegrity =
typeof CSS !== 'undefined' &&
typeof CSS.supports === 'function' &&
CSS.supports(
'background-image',
'url("https://example.com/a.svg" cross-origin(anonymous) referrer-policy(no-referrer) integrity("sha384-Iw/0p59dP96nGTzHvf2XIfqcBwBW7RM6JfOij8uZxyg5azfNaOOUW8SQy6H/hU91"))',
);
return { supportsCrossOriginAndReferrer, supportsUrlIntegrity };
}