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.
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.
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.
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-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.
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.
<!-- 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 |
<%- (unescaped) statt <%= (escaped) verwenden — andernfalls werden die + und / im Base64-Hash HTML-enkodiert und der Browser lehnt den Hash ab. 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 — 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',
}),
],
}; npm install --save-dev webpack-subresource-integrity 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. 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.
# 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 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.