CDN-Skripte gegen stille Manipulation absichern
Wer JavaScript oder CSS von einem externen CDN einbindet, vertraut darauf, dass der Anbieter niemals kompromittiert wird. Subresource Integrity ersetzt dieses blinde Vertrauen durch eine kryptographische Prüfsumme, die der Browser vor der Ausführung gegen den tatsächlichen Dateiinhalt abgleicht, und macht so stille Supply Chain Angriffe technisch sichtbar.
Inhaltsverzeichnis
Elf Abschnitte, von der Risikoeinordnung über Hash-Generierung bis zur automatisierten Build Pipeline Integration.
- 1. Warum CDN-Einbindung ein Supply Chain Risiko ist
- 2. Wie das integrity Attribut technisch funktioniert
- 3. Hashes generieren: openssl, npm-Tools und Build-Integration
- 4. Das crossorigin Attribut und CORS-Voraussetzungen
- 5. Versionierung: warum SRI Auto-Updates verhindert
- 6. Fallback-Strategien bei fehlgeschlagener Integritätsprüfung
- 7. SRI in Build-Pipelines automatisch pflegen
- 8. Typische Fehler bei der SRI-Einführung
- 9. SRI im Vergleich zu anderen CDN-Schutzmaßnahmen
- 10. Zusammenfassung
- 11. FAQ
1. Warum CDN-Einbindung ein Supply Chain Risiko ist
Subresource Integrity löst ein Problem, das viele Teams unterschätzen: Sobald eine Anwendung ein Skript von einem fremden CDN einbindet, etwa <script src="https://cdn.example.com/lib.js">, hat der Betreiber dieses CDN vollständige Kontrolle über den ausgeführten Code. Wird das CDN kompromittiert, sei es durch einen gestohlenen API Key, eine Schwachstelle im Build System des Anbieters oder einen böswilligen Mitarbeiter, kann jede Website, die dieses Skript einbindet, plötzlich manipulierten Code ausführen, ohne dass am eigenen Quelltext auch nur eine Zeile geändert wurde.
Solche Vorfälle sind keine Theorie: Mehrere große Supply Chain Angriffe der letzten Jahre liefen genau über diesen Weg, ein kompromittiertes npm Paket oder ein manipuliertes CDN Skript infizierte tausende nachgelagerte Websites gleichzeitig. Subresource Integrity begegnet diesem Risiko mit einem einfachen Prinzip: Der Browser lädt das Skript zwar weiterhin vom CDN, führt es aber nur aus, wenn der berechnete Hash exakt mit dem im HTML angegebenen Hash übereinstimmt. Jede Manipulation, und sei es nur ein einziges verändertes Byte, führt zur sofortigen Blockade.
Für Shopbetreiber ist dieses Risiko besonders relevant, weil Checkout Seiten häufig mehrere Drittanbieter Skripte gleichzeitig laden, etwa für Zahlungsabwicklung, Betrugserkennung und Tracking. Ein einziges kompromittiertes CDN Skript in dieser Kette reicht aus, um Kreditkartendaten sämtlicher Kunden abzugreifen, ohne dass der Shopbetreiber selbst jemals eine Zeile eigenen Codes verändert hat.
2. Wie das integrity Attribut technisch funktioniert
Für Entwickler, die zum ersten Mal mit Subresource Integrity arbeiten, lohnt sich ein kurzer Blick auf die zugrunde liegende Spezifikation der W3C Web Application Security Working Group, die den genauen Prüfalgorithmus und die unterstützten Hash Verfahren verbindlich festlegt.
Das integrity Attribut wird an script und link Elementen gesetzt und enthält einen Base64 kodierten kryptographischen Hash der erwarteten Datei, präfixiert mit dem verwendeten Algorithmus. Unterstützt werden sha256, sha384 und sha512, wobei sha384 in der Praxis der gängige Standard ist, weil er einen guten Kompromiss zwischen kryptographischer Stärke und Hash Länge im HTML bietet.
Sobald der Browser die Ressource heruntergeladen hat, berechnet er selbst den Hash über den empfangenen Byte Strom und vergleicht ihn mit dem Wert im integrity Attribut. Stimmen beide überein, wird das Skript ausgeführt oder das Stylesheet angewendet. Weichen sie voneinander ab, verwirft der Browser die Ressource komplett und meldet einen Fehler in der Konsole, ohne dass auch nur ein Teil des manipulierten Codes zur Ausführung kommt. Dieser Mechanismus arbeitet vollständig clientseitig und benötigt keine Serverkonfiguration auf Seiten des CDN.
<!-- SRI-protected CDN script with crossorigin and integrity hash -->
<script
src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"
integrity="sha384-6e6dNn0hPzP0X8qb9y1L8qBk8G3vJm3lJt2R6t9E5Qx1Zz3lQxq2s9jY7v3H5rV1"
crossorigin="anonymous"
></script>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/normalize.css@8.0.1/normalize.min.css"
integrity="sha384-4d3P6q2X9y5t7Z8k1J0nQ2wR5o3Vc7Tt6y8B9x2K1L4M0N7P3q6R9t2Y5w8Z1a3"
crossorigin="anonymous"
>
3. Hashes generieren: openssl, npm-Tools und Build-Integration
Der korrekte Hash lässt sich mit Bordmitteln über openssl berechnen, indem die Datei zunächst per curl heruntergeladen und anschließend gehasht wird. Wichtig ist, dass der Hash über exakt die Bytes berechnet wird, die der Browser tatsächlich empfängt, inklusive etwaiger Kompressions- oder Encoding-Unterschiede, die manche CDNs je nach Accept-Encoding Header ausliefern.
Für npm basierte Projekte existieren spezialisierte Pakete wie ssri, die den Hash direkt aus lokal installierten node_modules Dateien erzeugen und damit sicherstellen, dass die Version im Hash exakt der Version im package.json Lockfile entspricht. Diese Automatisierung ist wichtig, weil ein manuell berechneter Hash schnell veraltet, sobald ein Paket Update eingespielt wird, und ein vergessenes Hash Update dazu führt, dass die Anwendung nach jedem Dependency Update komplett ausfällt.
# Compute SRI hash manually with openssl and base64
curl -s https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js \
| openssl dgst -sha384 -binary \
| openssl base64 -A
# Or with the ssri npm package against a local file
npx ssri generate node_modules/chart.js/dist/chart.umd.min.js --algorithms sha384
# Verify an existing hash against the currently published CDN file
curl -s https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js \
| openssl dgst -sha384 -binary | openssl base64 -A
Ein wiederkehrender Verifikationsschritt in der CI Pipeline, der den im HTML hinterlegten Hash gegen eine frisch heruntergeladene Kopie der Datei prüft, deckt zuverlässig auf, wenn ein CDN Anbieter unerwartet den Inhalt hinter einer versionierten URL ausgetauscht hat, was eigentlich nie vorkommen sollte, aber in der Praxis gelegentlich doch passiert.
4. Das crossorigin Attribut und CORS-Voraussetzungen
Ein häufig übersehener Baustein bei Subresource Integrity ist das crossorigin Attribut, das zwingend gesetzt werden muss, sobald die Ressource von einer anderen Origin geladen wird. Ohne crossorigin="anonymous" verweigert der Browser dem JavaScript Zugriff auf die Antwortdaten zur Hash Berechnung, selbst wenn der Server technisch erreichbar ist, und die Integritätsprüfung schlägt grundsätzlich fehl.
Der CDN Server muss dafür passende CORS Header wie Access-Control-Allow-Origin: * ausliefern, sonst verweigert der Browser bereits das Laden der Ressource im Zusammenspiel mit crossorigin. Die meisten großen CDNs wie jsDelivr, cdnjs oder unpkg liefern diese Header standardmäßig aus, ein selbst gehostetes internes CDN muss diese Konfiguration jedoch explizit vornehmen, sonst funktioniert Subresource Integrity für interne Ressourcen nicht.
5. Versionierung: warum SRI Auto-Updates verhindert
Ein zentraler Effekt von Subresource Integrity, der oft als Nachteil missverstanden wird, ist die vollständige Unterbindung automatischer Updates über URLs ohne feste Version, etwa cdn.example.com/lib/latest/app.js. Da der Hash exakt zu einer einzigen Dateiversion passt, muss jede neue Version des CDN Skripts explizit mit einem neuen Hash im HTML nachgezogen werden. Das ist gewollt: Ohne diese Bindung könnte der CDN Betreiber die Datei hinter derselben URL jederzeit austauschen, und Subresource Integrity würde nur die erste Version schützen.
Für Projekte, die auf schnelle Sicherheitsupdates von Drittbibliotheken angewiesen sind, bedeutet das einen zusätzlichen Wartungsschritt: Jedes Update einer CDN Abhängigkeit erfordert das Neuberechnen des Hashes im selben Commit. Diese Kopplung erzwingt eine bewusste, überprüfbare Update Entscheidung statt eines stillen, unkontrollierten Austauschs im Hintergrund, was langfristig die Nachvollziehbarkeit von Drittanbieter Code deutlich verbessert.
6. Fallback-Strategien bei fehlgeschlagener Integritätsprüfung
Schlägt die Integritätsprüfung fehl, lädt der Browser die Ressource nicht, führt aber auch keinen automatischen Fallback aus, das muss die Anwendung selbst über das onerror Ereignis abfangen. Eine robuste Strategie lädt bei einem fehlgeschlagenen CDN Skript eine lokal gehostete Kopie derselben Version nach, damit die Anwendung nicht komplett ausfällt, nur weil ein externes CDN vorübergehend nicht erreichbar oder kompromittiert ist.
Wichtig ist, den Fallback nicht als reine Verfügbarkeitsmaßnahme zu verstehen, sondern auch als Sicherheitsnetz: Ein lokal gehostetes, aus derselben vertrauenswürdigen Build Pipeline stammendes Skript unterliegt nicht denselben Supply Chain Risiken wie das externe CDN. Für kritische Anwendungen, etwa Checkout Prozesse in einem Onlineshop, ist ein lokaler Fallback ohne externe Abhängigkeit oft die robustere Grundentscheidung, mit CDN Einbindung nur als Performance Optimierung über Caching.
// Fallback to a locally hosted copy if the SRI-protected CDN script fails to load
function loadWithFallback(cdnSrc, cdnIntegrity, localSrc) {
const script = document.createElement('script');
script.src = cdnSrc;
script.integrity = cdnIntegrity;
script.crossOrigin = 'anonymous';
script.onerror = () => {
console.warn('CDN script blocked or unreachable, loading local fallback');
const fallback = document.createElement('script');
fallback.src = localSrc; // no integrity needed for same-origin trusted build
document.head.appendChild(fallback);
};
document.head.appendChild(script);
}
// Usage: checkout page loads a payment SDK with automatic local fallback
loadWithFallback(
'https://js.paymentprovider.example/v3/sdk.js',
'sha384-9y1P0X8qb9y1L8qBk8G3vJm3lJt2R6t9E5Qx1Zz3lQxq2s9jY7v3H5rV1Z8k1J0n',
'/assets/vendor/payment-sdk-fallback.js'
);
Für Checkout kritische Skripte ist es ratsam, den Fallback Aufruf so früh wie möglich im Ladeprozess zu platzieren und den restlichen Checkout Ablauf erst zu starten, nachdem entweder das CDN Skript oder die lokale Kopie erfolgreich geladen wurde. Ein Timeout von wenigen Sekunden verhindert, dass Kunden bei einem lahmenden, aber nicht vollständig ausgefallenen CDN unnötig lange auf eine Reaktion warten.
7. SRI in Build-Pipelines automatisch pflegen
Manuell gepflegte Hashes veralten in der Praxis schnell, deshalb integrieren produktive Setups die Hash Berechnung direkt in den Build Prozess. Webpack Plugins wie webpack-subresource-integrity berechnen Hashes für jedes gebündelte Asset automatisch und schreiben sie in die generierten HTML Dateien, ganz ohne manuellen Eingriff bei jedem Deployment.
Für Projekte, die weiterhin externe CDN Skripte referenzieren, lohnt sich ein dediziertes Build Skript, das bei jedem Dependency Update automatisch neue Hashes zieht und einen Pull Request mit der Änderung öffnet. Diese Automatisierung verhindert den häufigsten praktischen Fehler bei Subresource Integrity: einen veralteten Hash, der nach einem CDN seitigen Update zu einer kompletten Blockade der Anwendung führt, weil niemand den Hash rechtzeitig aktualisiert hat.
8. Typische Fehler bei der SRI-Einführung
Der häufigste Fehler ist das Vergessen des crossorigin Attributs, was die Integritätsprüfung unabhängig vom korrekten Hash grundsätzlich scheitern lässt. Ein zweiter Fehler ist die Verwendung von latest oder ähnlichen unversionierten URLs zusammen mit einem statischen Hash, was garantiert nach dem nächsten CDN Update fehlschlägt, sobald sich der Dateiinhalt hinter derselben URL ändert.
Ein dritter, subtilerer Fehler betrifft Hash Berechnung über eine komprimierte statt der unkomprimierten Übertragung. Manche CDNs liefern je nach Accept-Encoding unterschiedlich komprimierte Varianten aus, der Hash muss aber exakt zu dem Byte Strom passen, den der jeweilige Client tatsächlich empfängt. In der Praxis empfiehlt es sich, den Hash direkt aus der offiziellen Distribution des Pakets zu ziehen, etwa über ssri gegen die lokale node_modules Datei, statt ihn manuell gegen eine live abgerufene CDN URL zu berechnen.
9. SRI im Vergleich zu anderen CDN-Schutzmaßnahmen
Neben Subresource Integrity existieren weitere Ansätze, um CDN Risiken zu begrenzen. Die folgende Tabelle stellt sie im direkten Vergleich gegenüber.
| Maßnahme | Schützt vor | Aufwand | Grenzen |
|---|---|---|---|
| Subresource Integrity | Manipulierten Dateiinhalt am CDN | Hash Pflege pro Version | Kein Schutz vor komplett neuer, bösartiger URL |
| Content Security Policy (script-src) | Skripte von nicht erlaubten Domains | Header Pflege, Domain Liste | Schützt nicht vor Manipulation der erlaubten Domain selbst |
| Selbst gehostete Kopie | Jedes externe CDN Risiko vollständig | Eigene Hosting und Update Pflicht | Kein automatisches CDN Caching mehr |
In der Praxis ist die Kombination aus Subresource Integrity und einer restriktiven Content Security Policy die robusteste Lösung: Die Content Security Policy begrenzt erlaubte Domains, Subresource Integrity stellt sicher, dass selbst eine erlaubte Domain keinen manipulierten Inhalt ausliefern kann, ohne dass der Browser dies bemerkt.
Mironsoft
Supply Chain Sicherheit, CDN Härtung und Build Pipeline Automatisierung
CDN-Skripte gegen stille Manipulation absichern?
Wir prüfen bestehende CDN Einbindungen, ergänzen fehlende integrity Hashes und automatisieren die Hash Pflege direkt in eurer Build Pipeline, inklusive Fallback Strategie für kritische Anwendungsteile.
CDN Audit
Analyse aller extern eingebundenen Skripte und Stylesheets
Hash Automatisierung
Build Pipeline Integration für automatische Hash Aktualisierung
Fallback Design
Lokale Fallback Strategie für kritische Checkout und Login Flows
Für Magento und Hyvä Shops mit mehreren extern eingebundenen Zahlungs und Tracking Skripten empfiehlt sich ein zentrales Modul, das alle SRI Hashes an einer einzigen Stelle im Layout XML pflegt, statt sie über verschiedene Templates zu verstreuen. Das erleichtert spätere Audits und macht sichtbar, welche externen Abhängigkeiten überhaupt aktiv im Checkout eingebunden sind.
10. Zusammenfassung
Subresource Integrity schließt eine Lücke, die viele Teams erst nach einem konkreten Vorfall ernst nehmen: blindes Vertrauen in externe CDN Anbieter. Über das integrity Attribut mit einem SHA-384 Hash und das zwingend nötige crossorigin Attribut stellt der Browser sicher, dass nur exakt der erwartete Dateiinhalt ausgeführt wird, jede Manipulation am CDN wird technisch sichtbar und blockiert.
Die versionsgebundene Natur von Subresource Integrity erzwingt bewusste, nachvollziehbare Updates statt stiller Änderungen im Hintergrund, was den zusätzlichen Wartungsaufwand rechtfertigt. Build Pipeline Integration über Tools wie webpack-subresource-integrity oder ssri reduziert diesen Aufwand auf ein Minimum und macht Subresource Integrity zu einer der wenigen Sicherheitsmaßnahmen, die sich fast vollständig automatisieren lassen, ohne die Entwicklungsgeschwindigkeit zu bremsen.
Subresource Integrity richtig nutzen — Das Wichtigste auf einen Blick
integrity Attribut
SHA-384 Hash im integrity Attribut blockiert manipulierte Dateien, bevor sie ausgeführt werden.
crossorigin Pflicht
Ohne crossorigin="anonymous" schlägt die Integritätsprüfung bei fremder Origin grundsätzlich fehl.
Versionierung
SRI verhindert Auto-Updates über unversionierte URLs, jede neue Version braucht einen neuen Hash.
Automatisierung
Build Pipeline Tools wie webpack-subresource-integrity oder ssri pflegen Hashes ohne manuellen Aufwand.
Gemeinsam ergeben diese vier Bausteine einen belastbaren Schutz gegen manipulierte CDN Skripte im laufenden Betrieb.