Signatur
Beschreibung
Die Eigenschaft integrity spiegelt das gleichnamige HTML-Attribut eines <script>-Elements wider. Sie enthält einen oder mehrere durch Leerzeichen getrennte Hash-Werte im Format algorithmus-base64hash, z. B. sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC. Unterstützt werden die Algorithmen sha256, sha384 und sha512.
Dieser Mechanismus heißt Subresource Integrity (SRI). Bevor der Browser ein extern geladenes Skript ausführt, berechnet er dessen Hash und vergleicht ihn mit dem angegebenen Wert. Stimmen die Werte nicht überein, wird das Skript nicht ausgeführt, und das Element löst ein error-Ereignis aus. So schützen Sie Ihre Seite davor, dass kompromittierte CDNs oder Man-in-the-Middle-Angreifer manipulierten Code einschleusen.
Relevant ist die Eigenschaft vor allem, wenn Sie Skripte dynamisch per JavaScript einfügen: Dann setzen Sie integrity (und für fremde Ursprünge zusätzlich crossOrigin), bevor Sie das Element ins Dokument einhängen. Enthält die Eigenschaft einen leeren String, findet keine Integritätsprüfung statt.
Rückgabewert
integrity-Attributs, z. B. "sha384-…". Ist das Attribut nicht gesetzt, wird ein leerer String "" zurückgegeben. Beim Setzen wird das HTML-Attribut entsprechend aktualisiert.Beispiele
Skript dynamisch mit SRI-Hash von einem CDN laden
const loadScript = (src, hash) => new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = src;
script.integrity = hash; // Hash vor dem Einfügen setzen
script.crossOrigin = 'anonymous'; // Pflicht für fremde Ursprünge
script.onload = () => resolve(script);
script.onerror = () => reject(new Error(`Integritätsprüfung oder Laden fehlgeschlagen: ${src}`));
document.head.append(script);
});
try {
await loadScript(
'https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js',
'sha384-DEIN_HASH_HIER'
);
console.log('Skript geprüft und geladen');
} catch (err) {
console.error(err.message);
}
Integrity-Wert vorhandener Skripte auslesen
// Alle externen Skripte ohne SRI-Schutz finden (Sicherheits-Audit)
const unprotected = [...document.scripts]
.filter((s) => s.src && !s.integrity)
.map((s) => s.src);
console.log('Skripte ohne integrity:', unprotected);
SRI-Hash im Browser selbst berechnen
const computeSri = async (url, algo = 'SHA-384') => {
const buffer = await (await fetch(url)).arrayBuffer();
const digest = await crypto.subtle.digest(algo, buffer);
const base64 = btoa(String.fromCharCode(...new Uint8Array(digest)));
return `${algo.toLowerCase().replace('-', '')}-${base64}`;
};
const hash = await computeSri('/js/app.js');
const script = document.createElement('script');
script.src = '/js/app.js';
script.integrity = hash;
document.body.append(script);
console.log(script.integrity);
// Wichtig · Fallstricke
- CORS erforderlich: Für Skripte von fremden Ursprüngen muss
crossOrigingesetzt sein ("anonymous"oder"use-credentials"), und der Server muss passendeAccess-Control-Allow-Origin-Header senden. Fehlen diese, schlägt die Prüfung immer fehl und das Skript wird blockiert. - Zeitpunkt:
integritymuss gesetzt sein, bevor das Element ins DOM eingefügt wird. Spätere Änderungen wirken sich nicht mehr auf das bereits gestartete Laden aus. - Inline-Skripte: Bei Skripten ohne
srchat das Attribut keine Wirkung. Für Inline-Code nutzen Sie stattdessen CSP-Hashes (script-src 'sha256-…'). - Versionierung: Jede Änderung an der Datei (auch ein Minify-Update auf dem CDN) macht den Hash ungültig. Binden Sie deshalb immer eine feste Version ein (z. B.
lodash@4.17.21) und keine „latest“-URLs. - Bei mehreren Hashes nutzt der Browser den stärksten unterstützten Algorithmus; empfohlen ist
sha384. - Verwenden Sie
crypto.subtle.digest()nur in sicheren Kontexten (HTTPS). Einen zur Laufzeit berechneten Hash einer gerade geladenen Datei zu verwenden, bietet keinen echten Schutz. Berechnen Sie Hashes deshalb beim Build und hinterlegen Sie sie fest im Code. - Kompatibilität: wird von allen modernen Browsern unterstützt, im Internet Explorer nicht (dort wird das Attribut ignoriert).