Start · Sprachen · JavaScript · Referenz · HTMLLinkElement.integrity

HTMLLinkElement.integrity

Eigenschaft

Liest oder setzt den Wert des <code>integrity</code>-Attributs eines <code>&lt;link&gt;</code>-Elements, mit dem der Browser per Subresource Integrity (SRI) prüft, ob eine Ressource unverändert ist.

seit JavaScript Baseline: alle modernen Browser (Chrome 45+, Firef Kategorie: webapi

Signatur

HTMLLinkElement.integrity

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

Typ
string
Beschreibung
Der aktuelle Wert des 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]));
sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH ["sha384"]

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);
}
Stylesheet geladen und verifiziert

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-'));
true

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);
(Tabelle mit URLs externer Stylesheets ohne integrity-Attribut)

// Wichtig · Fallstricke

  • CORS ist Pflicht bei fremden Ursprüngen: Ohne crossorigin-Attribut bzw. crossOrigin-Eigenschaft oder ohne Access-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 vor href bzw. vor dem Einfügen ins Dokument.
  • Preload und Verwendung müssen zusammenpassen: Hat ein rel="preload" einen anderen integrity-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-for ist veraltet und wird nicht unterstützt.
  • Empfohlen wird sha384 oder sha512. 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.