SRI für Express.js konfigurieren

Schritt-für-Schritt-Anleitung: SRI-Hashes mit dem Node.js crypto-Modul generieren, in Template-Engines einbinden und mit dem Webpack-Plugin vollständig automatisieren.

Express · Schritt für Schritt

SRI in Express.js und Node.js

Express.js bietet mit dem eingebauten crypto-Modul alles, was für die programmatische SRI-Hash-Generierung nötig ist — kein externes Paket erforderlich. Hashes werden beim Server-Start einmalig berechnet und als Template-Variable an EJS, Pug oder Handlebars übergeben. Für Build-Pipelines mit Webpack übernimmt das Plugin webpack-subresource-integrity die vollautomatische Generierung.

SRI bringt 15 von 166 Punkten im Wolf-Agents Web Security Check. Diese Anleitung zeigt alle vier Schritte: Hash-Generierung via crypto, Template-Integration, Webpack-Automatisierung und abschließende Verifizierung. Die Ansätze sind kombinierbar — lokale Assets manuell hashen, CDN-Ressourcen aus der Anbieter-Dokumentation übernehmen.

1 Schritt 1 von 4

SRI-Hashes programmatisch generieren

Das crypto-Modul ist fester Bestandteil von Node.js — keine Installation nötig. Die Funktion generateSRI() liest die Asset-Datei, berechnet den SHA-384-Hash und gibt den fertigen integrity-Attributwert zurück. Hashes einmalig beim Server-Start berechnen, um I/O pro Request zu vermeiden.

server.js crypto
const crypto = require('crypto');
const fs = require('fs');

// Hilfsfunktion: SRI-Hash aus lokaler Datei generieren
function generateSRI(filePath) {
  const content = fs.readFileSync(filePath);
  const hash = crypto
    .createHash('sha384')
    .update(content)
    .digest('base64');
  return `sha384-${hash}`;
}

// Hashes beim Server-Start einmalig berechnen
const bootstrapHash = generateSRI('./public/js/bootstrap.min.js');
const mainCssHash  = generateSRI('./public/css/main.min.css');

// Hash an Template übergeben
app.get('/', (req, res) => {
  res.render('index', {
    bootstrapSri: bootstrapHash,
    mainCssSri:   mainCssHash,
  });
});
SHA-384 empfohlen

SHA-256 ist das Minimum, SHA-384 der empfohlene Standard (NIST-konform, ausreichend sicher, gute Performance). SHA-512 bietet maximale Sicherheit, erzeugt aber längere Strings. Verwenden Sie konsistent denselben Algorithmus für alle Hashes.

2 Schritt 2 von 4

Template-Integration (EJS/Pug/Handlebars)

Die generierten Hashes werden über res.render() als Template-Variablen übergeben und im integrity-Attribut von <script>- und <link>-Tags eingesetzt. Das crossorigin="anonymous"-Attribut ist bei Cross-Origin-Ressourcen Pflicht — ohne es kann der Browser den Hash nicht verifizieren.

views/index.ejs / index.pug Template
<!-- EJS-Template: integrity-Attribut mit übergebenem Hash -->
<link
  rel="stylesheet"
  href="/css/main.min.css"
  integrity="<%- mainCssSri %>"
  crossorigin="anonymous"
/>

<script
  src="/js/bootstrap.min.js"
  integrity="<%- bootstrapSri %>"
  crossorigin="anonymous"
  defer
></script>

<!-- Pug-Template (Äquivalent) -->
link(rel='stylesheet' href='/css/main.min.css' integrity=mainCssSri crossorigin='anonymous')
script(src='/js/bootstrap.min.js' integrity=bootstrapSri crossorigin='anonymous' defer)
Template-Engine Syntax für Hash-Ausgabe HTML-Escaping
EJS <%- variable %> Kein Escaping (raw output)
Pug integrity=variable Automatisch korrekt
Handlebars {{{variable}}} Triple-Braces für raw output
Bei EJS unbedingt <%- (unescaped) statt <%= (escaped) verwenden — andernfalls werden die + und / im Base64-Hash HTML-enkodiert und der Browser lehnt den Hash ab.
3 Schritt 3 von 4

Webpack-Plugin für automatische Generierung

Das Plugin webpack-subresource-integrity berechnet SRI-Hashes zur Build-Zeit automatisch für alle generierten Chunk-Dateien und fügt die integrity-Attribute in das HTML-Bundle ein. Voraussetzung ist crossOriginLoading: 'anonymous' in der Webpack-output-Konfiguration.

webpack.config.js Plugin
// webpack.config.js — automatische SRI-Hash-Generierung
const { SubresourceIntegrityPlugin } = require('webpack-subresource-integrity');

module.exports = {
  output: {
    // Pflicht: crossOriginLoading muss gesetzt sein
    crossOriginLoading: 'anonymous',
  },
  plugins: [
    new SubresourceIntegrityPlugin({
      // sha384 ist empfohlener Algorithmus (NIST-konform)
      hashFuncNames: ['sha384'],
      enabled: process.env.NODE_ENV === 'production',
    }),
  ],
};
Plugin installieren:
npm install --save-dev webpack-subresource-integrity
Das Plugin setzt enabled: process.env.NODE_ENV === 'production' empfohlen — im Development-Modus erzeugte Bundles ändern sich häufig und der Hash-Overhead ist unnötig. In Production ist automatische SRI-Generierung der manuelle Ansatz jedoch immer vorzuziehen.
4 Schritt 4 von 4

Verifizierung

Nach dem Start prüfen Sie, ob die integrity-Attribute korrekt im gerenderten HTML erscheinen. Mit curl und grep ist das schnell erledigt. Manuell können Sie jeden Hash mit openssl nachrechnen — das Ergebnis muss identisch sein.

Terminal Verifizierung
# 1. Server starten und Response prüfen
node server.js

# 2. HTML-Ausgabe auf integrity-Attribute prüfen
curl -s http://localhost:3000 | grep -E 'integrity='

# Erwartete Ausgabe (Beispiel):
# integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"

# 3. Hash einer Datei manuell verifizieren
cat ./public/js/bootstrap.min.js | openssl dgst -sha384 -binary | openssl base64 -A
Browser-Konsole als Diagnosetool

Schlägt die SRI-Prüfung fehl, zeigt die Browser-Konsole einen Fehler: "Failed to find a valid digest in the 'integrity' attribute". Häufige Ursachen: Hash falsch berechnet (Datei wurde nach Berechnung geändert), fehlendes crossorigin-Attribut, oder HTML-Escaping hat den Base64-String korrumpiert.

Wie steht Ihre Domain bei Subresource Integrity?

Prüfen Sie es jetzt — kostenlos, ohne Registrierung, mit 166 Prüfpunkte.

Häufig gestellte Fragen

Wie generiere ich SRI-Hashes in Node.js?

Mit dem eingebauten crypto-Modul: fs.readFileSync() liest die Datei, crypto.createHash("sha384").update(inhalt).digest("base64") berechnet den Hash. Der integrity-Wert ist dann sha384- + base64-Hash. Kein externes Paket nötig — crypto ist Teil von Node.js core.

Funktioniert SRI nur für lokale Dateien oder auch für CDN-Ressourcen?

SRI funktioniert für beides. Für lokale Dateien berechnen Sie den Hash selbst (crypto-Modul). Für CDN-Ressourcen (Bootstrap, jQuery etc.) entnehmen Sie den Hash direkt aus der offiziellen Dokumentation des CDN-Anbieters oder berechnen ihn aus der heruntergeladenen Originaldatei.

Kann ich Helmet.js zusammen mit SRI nutzen?

Ja, und das ist empfehlenswert. Helmet setzt wichtige HTTP-Security-Header wie Content-Security-Policy, X-Content-Type-Options und weitere. SRI und CSP ergänzen sich: CSP kann require-sri-for script style erzwingen, sodass der Browser SRI für alle externen Ressourcen vorschreibt. Kombinieren Sie helmet() mit SRI für maximalen Schutz.

Wie integriere ich SRI-Hashes in EJS-Templates?

Übergeben Sie die Hashes als Template-Variablen über res.render(): res.render("index", { bootstrapSri: generateSRI("./public/js/bootstrap.min.js") }). Im Template referenzieren Sie sie mit <%- bootstrapSri %> im integrity-Attribut.

Was passiert, wenn ein Build-Asset sich ändert und der Hash veraltet ist?

Der Browser blockiert die Ressource — sie wird nicht geladen. Deshalb sollte der Hash bei jedem Build neu generiert werden. Das Webpack-Plugin webpack-subresource-integrity erledigt das automatisch. Bei manueller Verwaltung bauen Sie die Hash-Generierung in Ihr Build-Script ein.

Brauche ich das crossorigin-Attribut auch bei lokalen Dateien?

Bei same-origin Ressourcen (eigener Server) ist crossorigin technisch nicht zwingend erforderlich, schadet aber nicht. Bei Cross-Origin-Ressourcen (CDN, externe Domains) ist crossorigin="anonymous" Pflicht — ohne es kann der Browser den Dateiinhalt nicht lesen und den SRI-Hash nicht prüfen.

Unterstützt das webpack-subresource-integrity Plugin alle Module-Typen?

Das Plugin unterstützt Script- und Style-Assets, die von Webpack generiert werden. Voraussetzung ist output.crossOriginLoading: "anonymous" in der Webpack-Konfiguration. Externe Assets, die nicht durch den Webpack-Bundle-Prozess laufen, müssen separat behandelt werden.