Signatur
Beschreibung
Die Eigenschaft integrity spiegelt das gleichnamige HTML-Attribut eines <link>-Elements wider. Sie enthält einen oder mehrere kryptografische Hashes im Format <algorithmus>-<base64-hash>, z. B. sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC. Unterstützt werden sha256, sha384 und sha512. Mehrere Hashes werden durch Leerzeichen getrennt.
Dieser Mechanismus heißt Subresource Integrity (SRI). Der Browser lädt die Ressource, berechnet ihren Hash und vergleicht ihn mit dem angegebenen Wert. Stimmt er nicht überein, verwirft der Browser die Ressource: Ein Stylesheet wird dann nicht angewendet, ein Preload nicht verwendet, und am Element wird ein error-Event ausgelöst. So schützt man sich davor, dass ein kompromittiertes CDN manipulierte Dateien ausliefert.
Relevant ist integrity vor allem bei rel="stylesheet", rel="preload" und rel="modulepreload". Bei Ressourcen von fremden Ursprüngen muss zusätzlich crossorigin gesetzt sein (meist "anonymous") und der Server muss passende CORS-Header senden. Sonst schlägt die Prüfung immer fehl.
Wenn Sie Elemente per JavaScript erzeugen, müssen Sie integrity und crossOrigin setzen, bevor Sie href zuweisen bzw. das Element ins Dokument einfügen. Nur dann werden die Werte beim Laden berücksichtigt.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $value | string | "" | Beim Setzen: ein oder mehrere durch Leerzeichen getrennte Hash-Ausdrücke im Format sha256-…, sha384-… oder sha512-…. Ein leerer String deaktiviert die Prüfung. |
Rückgabewert
integrity-Attributs. Ist das Attribut nicht gesetzt, ist es ein leerer String "".Beispiele
Integrity-Wert eines vorhandenen Stylesheets auslesen
// HTML: <link id="bs" rel="stylesheet"
// href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
// integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH"
// crossorigin="anonymous">
const link = document.getElementById('bs');
console.log(link.integrity);
console.log(link.integrity.split(' ').map((h) => h.split('-')[0]));
Stylesheet von einem CDN dynamisch mit SRI laden
const loadStylesheet = (href, integrity) =>
new Promise((resolve, reject) => {
const link = document.createElement('link');
link.rel = 'stylesheet';
// integrity und crossOrigin VOR href setzen
link.integrity = integrity;
link.crossOrigin = 'anonymous';
link.href = href;
link.addEventListener('load', () => resolve(link));
link.addEventListener('error', () =>
reject(new Error(`Integritätsprüfung oder Laden fehlgeschlagen: ${href}`))
);
document.head.append(link);
});
try {
await loadStylesheet(
'https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css',
'sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH'
);
console.log('Stylesheet geladen und verifiziert');
} catch (err) {
console.error(err.message);
}
SRI-Hash im Browser berechnen und setzen
// Erzeugt einen sha384-Hash für eine Datei auf demselben Ursprung
const computeSri = async (url) => {
const buffer = await (await fetch(url)).arrayBuffer();
const digest = await crypto.subtle.digest('SHA-384', buffer);
const base64 = btoa(String.fromCharCode(...new Uint8Array(digest)));
return `sha384-${base64}`;
};
const hash = await computeSri('/css/app.css');
const preload = document.createElement('link');
preload.rel = 'preload';
preload.as = 'style';
preload.integrity = hash;
preload.href = '/css/app.css';
document.head.append(preload);
console.log(preload.integrity.startsWith('sha384-'));
Seiten prüfen: Welche externen Stylesheets haben kein SRI?
const unprotected = [...document.querySelectorAll('link[rel="stylesheet"]')]
.filter((l) => new URL(l.href).origin !== location.origin && !l.integrity)
.map((l) => l.href);
console.table(unprotected);
// Wichtig · Fallstricke
- CORS ist Pflicht bei fremden Ursprüngen: Ohne
crossorigin-Attribut bzw.crossOrigin-Eigenschaft oder ohneAccess-Control-Allow-Origin-Header vom Server schlägt die Prüfung immer fehl, und die Ressource wird blockiert. - Reihenfolge beim dynamischen Erzeugen: Ein nachträglich geänderter
integrity-Wert wirkt sich nicht auf eine Ressource aus, die schon geladen wurde. Setzen Sie ihn deshalb vorhrefbzw. vor dem Einfügen ins Dokument. - Preload und Verwendung müssen zusammenpassen: Hat ein
rel="preload"einen anderenintegrity-Wert als das spätere<link rel="stylesheet">oder<script>, verwirft der Browser die vorgeladene Ressource und lädt sie erneut. - Hash muss exakt passen: Schon ein geändertes Byte (Zeilenumbruch, neue Version beim CDN, Komprimierung durch einen Proxy) macht die Datei ungültig. Verwenden Sie deshalb nur versionierte, unveränderliche URLs.
- Sicherheit: SRI schützt nur vor Manipulation der geladenen Datei, aber nicht vor XSS in Ihrer eigenen Seite. Kombinieren Sie SRI mit einer Content Security Policy (CSP). Die frühere CSP-Direktive
require-sri-forist veraltet und wird nicht unterstützt. - Empfohlen wird
sha384odersha512. Bei mehreren Hashes verwendet der Browser nur die mit dem stärksten Algorithmus. - Unterstützung: in allen modernen Browsern vorhanden. Der Internet Explorer ignoriert das Attribut, die Ressource wird dort also ohne Prüfung geladen.