Die meisten Shop-Betreiber denken bei Sicherheit an das, was Kunden sehen: Login, Checkout, Zahlungsdaten. Die Wellen des Shai-Hulud-Wurms haben eine unbequemere Wahrheit sichtbar gemacht. Die größte Angriffsfläche ist nicht der Shop im Browser, sondern der Build. Schadcode verbreitet sich selbstreplizierend durch npm, trifft inzwischen auch Packagist und PyPI, und der Payload läuft in der preinstall-Phase — also bevor irgendein Test greift. Dieser Artikel zeigt, wie eine Storefront-Build-Kette real kompromittiert wird und mit welchen Maßnahmen Sie Ihre Entwicklungs- und Deployment-Prozesse härten.

Warum der Build gefährlicher ist als der Shop im Browser

Ein Angreifer, der Ihre Storefront übernehmen will, hat zwei Wege. Der erste führt durch das Frontend: SQL-Injection, XSS, Session-Übernahme, Brute Force gegen den Login. Gegen diesen Weg ist in den meisten Shops etwas gebaut — eine WAF, Rate Limits, gepflegte Updates. Der zweite Weg führt durch den Build. Und dort steht meist nichts.

Der Unterschied ist gravierend. Ein Frontend-Angriff liefert das, was die Anwendung zugesteht. Ein Build-Angriff liefert das, was Ihr CI-Runner darf: Deploy-Schlüssel, Datenbank-Zugangsdaten, Cloud-Credentials, Zahlungs-API-Keys, Registry-Tokens — in vielen Pipelines faktisch alles. composer update auf einem Runner ist damit privilegierter als jede Kundeninteraktion im Shop.

Die Grundlage dafür ist die schiere Menge fremden Codes. Ein Storefront-Projekt zieht über npm und Composer mehrere hundert bis mehrere tausend transitive Abhängigkeiten. Vielleicht zwanzig davon haben Sie bewusst ausgewählt; der Rest ist Code von Menschen, die Sie nicht kennen, ausgeführt mit den Rechten Ihrer Pipeline. Das BSI verzeichnet für Juli 2024 bis Juni 2025 durchschnittlich 119 (BSI) neue Schwachstellen pro Tag, rund 24% (BSI) mehr als im Vorjahr, bei einem Anstieg der Ausnutzung um 38% (BSI).

Dass die Lieferkette ein eigenständiges Problem ist, zeigt ein zweites Beispiel aus demselben Bericht: Bei zwei IoT-Botnetzen gelangte die Schadsoftware bereits im Produktionsprozess auf die Geräte. Rund 40.000 (BSI) kamen vorinfiziert in den Handel, ohne wirksame Gegenmaßnahme für Nutzende. Das ist die Logik eines Lieferkettenangriffs: Der Schaden entsteht, bevor der Betroffene entscheiden kann.

Der Perspektivwechsel

Die relevante Frage lautet nicht Ist mein Shop sicher?, sondern Was kann ein beliebiges npm- oder Composer-Paket in meiner Pipeline anrichten, wenn es morgen bösartig wird? Wer diese Frage nicht beantworten kann, hat kein Lieferketten-Problem in der Zukunft, sondern eine offene Flanke in der Gegenwart. Die Grundlagen dazu ordnet unser Überblick zur IT-Sicherheit im E-Commerce ein.

Shai-Hulud: ein Wurm, der sich selbst weiterreicht

Am 23. September 2025 veröffentlichte die US-Cybersicherheitsbehörde CISA eine Warnung zu einer weitreichenden Kompromittierung des npm-Ökosystems. Ein selbstreplizierender Wurm, öffentlich als Shai-Hulud bekannt, hatte zu diesem Zeitpunkt rund 500 (CISA) Pakete kompromittiert. Nach dem Erstzugriff durchsuchte die Schadsoftware die Umgebung nach Zugangsdaten und zielte dabei gezielt auf GitHub Personal Access Tokens sowie API-Schlüssel für Cloud-Dienste wie AWS, Google Cloud Platform und Microsoft Azure (CISA).

Der entscheidende Mechanismus ist die Selbstreplikation. Palo Alto Networks Unit 42 beschreibt ihn präzise: Die Schadsoftware erntet npm-Tokens von kompromittierten Entwicklern, identifiziert dann weitere Pakete, die derselbe Entwickler betreut, injiziert Schadcode in diese Pakete und veröffentlicht die neuen, kompromittierten Versionen in der Registry (Unit 42). Der Angriff braucht danach keinen Angreifer mehr. Er läuft.

Die zweite Welle im November 2025 fiel deutlich größer aus. Trojanisierte Pakete wurden zwischen dem 21. und 23. November 2025 hochgeladen (The Hacker News). Unit 42 zählt über 25.000 (Unit 42) bösartige Repositories über rund 350 (Unit 42) einzelne Nutzerkonten. Zum Zeitpunkt der Berichterstattung waren es bereits über 27.000 (The Hacker News) Repositories, mit rund 1.000 (The Hacker News) neuen Repositories alle 30 Minuten. Betroffen waren Maintainer-Konten aus Projekten wie Zapier, ENS Domains, PostHog und Postman (The Hacker News). Microsoft datiert den Kampagnenstart auf den 24. November 2025 (Microsoft Security).

Dazu kam ein destruktiver Rückfallmodus: Scheitert der Diebstahl, überschreibt und löscht die Schadsoftware jede beschreibbare Datei des Benutzers unterhalb seines Home-Verzeichnisses (Unit 42). Aus einem Datenabfluss wird ein Totalverlust der Arbeitsumgebung.

Registry-Tokens

npm-Zugangstokens aus .npmrc-Dateien — der Treibstoff der Selbstreplikation: Jeder erbeutete Token infiziert weitere Pakete (Unit 42).

GitHub-Zugriff

Personal Access Tokens und Actions-Secrets. Damit gehört dem Angreifer nicht nur der Build, sondern auch der Quellcode.

Cloud-Credentials

Umgebungsvariablen mit AWS-, GCP- und Azure-Schlüsseln (CISA), neuerdings auch AWS Secrets Manager und Instance Metadata Service (Microsoft Security).

Secret-Stores

Vault, Kubernetes-Tokens und Passwortmanager. Der Payload sucht parallel über mehr als ein Dutzend Token-Pfade (Microsoft Security).

SSH-Schlüssel

Private Schlüssel aus dem Home-Verzeichnis (Unit 42) — sie öffnen Server, die mit der Build-Kette nichts zu tun haben.

Wallets und Browserdaten

Kryptowährungs-Wallets und Browser-Profile — die Kampagne gilt als finanziell motiviert.

Im Mai 2026 folgte unter dem Namen Mini Shai-Hulud eine Welle über die übernommene npm-Organisation @antv. GitHub entfernte 640 (Microsoft Security) bösartige Pakete und invalidierte 61.274 (Microsoft Security) granulare npm-Tokens mit Schreibrechten. Der Payload war eine rund 499 KB (Microsoft Security) große, obfuskierte JavaScript-Datei, die still während npm install lief; über 2.200 (Microsoft Security) vom Angreifer erzeugte Repositories waren beobachtbar.

Das Muster hinter den Wellen

Kein einziger dieser Angriffe brauchte eine Schwachstelle in Ihrem Code. Er brauchte nur, dass Sie ein Update ziehen. Die Angriffskette beginnt bei einem fremden Maintainer-Konto und endet in Ihrer Pipeline — dazwischen liegt genau eine Entscheidung, die Sie kontrollieren: wann und wie Sie neue Versionen übernehmen.

preinstall: der Payload läuft, bevor ein Test greift

Der technisch wichtigste Punkt für Shop-Betreiber ist die Ausführungsphase. Die ursprüngliche Variante von Shai-Hulud lief über postinstall-Skripte, also nach der Installation. Die November-Eskalation wechselte auf preinstall und weitete damit die Wirkung auf Entwicklermaschinen und CI/CD-Pipelines erheblich aus, ohne dass eine menschliche Interaktion nötig war (Unit 42). Microsoft beschreibt denselben Kern: Der Schadcode wird in der preinstall-Phase infizierter npm-Pakete ausgeführt und läuft damit vor jeglichen Tests oder Sicherheitsprüfungen (Microsoft Security).

Das ist kein Detail, sondern der Bruch mit einer verbreiteten Annahme. Viele Teams glauben, ihre Pipeline sei ein Filter: installieren, testen, scannen, deployen — was faul ist, fällt im Test auf. Bei einem preinstall-Payload ist diese Reihenfolge wertlos: Der Schadcode hat die Tokens exfiltriert, bevor die erste Test-Suite startet. Ein Scanner, der danach anschlägt, dokumentiert einen Vorfall, er verhindert ihn nicht.

package.json (eines infizierten Pakets)
{
  "name": "harmlos-aussehende-utility",
  "version": "4.2.1",
  "scripts": {
    "preinstall": "node setup_bun.js"
  }
}

Microsoft dokumentiert für die Kampagne ein preinstall-Skript namens setup_bun.js beziehungsweise set_bun.js (Microsoft Security). Der Name ist beliebig austauschbar und sieht nach Build-Werkzeug aus. Entscheidend ist nicht der Name, sondern die Tatsache, dass ein Lifecycle-Hook existiert und Ihr Paketmanager ihn ohne Rückfrage ausführt.

PhaseWann sie läuftWas davor noch greift
postinstallNach der InstallationAuflösung und Download, sonst nichts
preinstallVor der InstallationNichts. Kein Test, kein Linter, kein Scanner
Composer autoload.filesBei jedem PHP-RequestSkript-Sperren greifen hier nicht
Test-SuiteNach dem InstallZu spät für beide Skript-Phasen

Die Konsequenz ist unbequem, aber sie ist der Ausgangspunkt jeder tragfähigen Absicherung: Der einzige Kontrollpunkt, der vor einem preinstall-Payload liegt, ist die Entscheidung, ob dieses Paket in dieser Version überhaupt installiert wird — und ob dabei Skripte laufen dürfen. Alles andere kommt zu spät.

Composer trifft es genauso — und subtiler

Wer aus der PHP-Welt kommt und Shopware, WooCommerce oder eine individuelle Storefront betreibt, könnte das npm-Problem für ein JavaScript-Problem halten. Das war es bis 2026. Am 22. und 23. Mai 2026 veröffentlichte ein Angreifer in schneller Folge, viele Versionen nur Sekunden auseinander, hunderte bösartige Versionen unter historischen Release-Tags für vier Lokalisierungsbibliotheken im laravel-lang-Namensraum auf Packagist (The Hacker News). Insgesamt wurden über 700 (The Hacker News) betroffene Versionen identifiziert.

Die Methode verdient besondere Aufmerksamkeit, weil sie eine verbreitete Schutzmaßnahme aushebelt. Der Angreifer veröffentlichte keine neue Version. Er schrieb jeden existierenden Git-Tag in jedem Repository so um, dass er auf einen neuen, bösartigen Commit zeigte (The Hacker News). Versions-Pinning schützt gegen neue Versionen. Es schützt nicht, wenn die alte, geprüfte Version unter derselben Nummer plötzlich anderen Code enthält.

Auch der Ausführungsweg war ein anderer. Statt eines Lifecycle-Skripts trug der Angreifer src/helpers.php in die autoload.files-Map jedes Pakets ein (The Hacker News). Da jede Laravel-Anwendung beim Start require __DIR__.'/vendor/autoload.php' aufruft, lief der Payload bei jedem PHP-Request. Der Stealer umfasste rund 5.900 (The Hacker News) Zeilen PHP, sammelte Cloud-Zugangsdaten, CI-Tokens, Browserdaten und SSH-Schlüssel, verschlüsselte alles mit AES-256 und löschte sich anschließend selbst.

Warum --no-scripts hier nicht reicht

Der laravel-lang-Angriff lief über den Composer-Autoloader, nicht über ein Lifecycle-Skript. Skript-Sperren wie --no-scripts greifen an dieser Stelle nicht. Das ist kein Argument gegen Skript-Kontrolle — es ist ein Argument dafür, dass eine einzelne Maßnahme nicht trägt. Erst die Kombination aus Cooldown, Prüfung des Lockfile-Diffs und begrenzten Rechten deckt beide Ausführungswege ab.

Eine weitere Kampagne im Mai 2026 arbeitete ökosystemübergreifend: Bei acht Packagist-Paketen lag der Schadcode nicht in der composer.json, sondern in der package.json (The Hacker News) — Ziel waren Projekte, die neben PHP auch JavaScript-Build-Werkzeuge ausliefern, also die typische moderne Storefront. Ein postinstall-Skript lud eine Linux-Binärdatei von einer GitHub-Releases-URL nach /tmp/.sshd und startete sie. Derselbe Payload fand sich in 777 (The Hacker News) Dateien auf GitHub. Wer nur Composer-Metadaten scannt, sieht davon nichts.

Packagist benennt die Vorfälle offen: intercom/intercom-php am 30. April 2026 und laravel-lang am 22. Mai 2026, beide über gestohlene Zugangsdaten (Packagist). Die Gegenmaßnahmen zeigen, welche Annahmen nicht mehr gelten: Stabile Versionen lassen sich nicht mehr still durch Git-Re-Tagging überschreiben, Tag-Änderungen werden abgelehnt und gemeldet. Composer 2.10 bringt ein Dependency-Policy-Framework für markierte Versionen, Schwachstellen und aufgegebene Pakete; geplant sind verpflichtende MFA und ein FIDO2-gestützter Release-Prozess (Packagist).

Wie eine Storefront-Build-Kette real kompromittiert wird

Abstrakte Angriffsklassen überzeugen selten ein Budget-Meeting. Die folgende Kette lässt sich aus den dokumentierten Vorfällen direkt in den Alltag einer Storefront übersetzen. Sie beginnt weit außerhalb Ihres Einflussbereichs und endet in Ihrer Produktionsumgebung.

  1. Ein Maintainer eines Pakets, das drei Ebenen unter Ihrer direkten Abhängigkeit liegt, verliert seinen Registry-Token — durch Phishing, einen Leak oder eine vorherige Infektion (Unit 42).
  2. Der Wurm veröffentlicht unter diesem Konto neue Versionen aller Pakete, die der Maintainer betreut. Der Schadcode hängt in einem preinstall-Hook (Microsoft Security).
  3. Ihr Renovate-Bot, ein Entwickler oder ein nächtlicher Build ruft npm install oder composer update auf. Die neue Version erfüllt Ihren Versions-Constraint und wird aufgelöst.
  4. Der preinstall-Hook läuft auf dem CI-Runner. Vor dem Test. Vor dem Scan. Vor dem Build.
  5. Der Payload durchsucht Umgebungsvariablen, Metadaten-Endpunkte, Vault-Pfade und .npmrc nach Zugangsdaten (Microsoft Security).
  6. Die Beute wird in ein öffentliches, vom Angreifer kontrolliertes Repository exfiltriert (Microsoft Security).
  7. Mit Ihrem Registry-Token infiziert der Wurm Ihre eigenen Pakete weiter. Sie werden vom Opfer zum Verteiler.

Was danach passiert, hängt allein von den Rechten ab, die Ihr Runner hatte: im ungünstigen Fall Deploy-Schlüssel für die Produktion, Datenbank-Zugangsdaten, der Zahlungs-API-Key und der Objektspeicher mit Kundendaten. Der Wurm muss diese Rechte nicht erraten — sie stehen in der Umgebung des Prozesses, den er gerade gestartet hat.

Der Payload läuft nicht, weil jemand einen Fehler gemacht hat. Er läuft, weil jemand ein Update gezogen hat — und weil zwischen Registry und Runner nichts stand.

XICTRON Entwicklungsteam

Ob Sie eine Shopware-Storefront betreuen, einen eigenen Frontend-Stack fahren oder auf WordPress aufsetzen: Sobald ein Paketmanager im Spiel ist, ist die Kette identisch. Ergänzende Härtung auf Anwendungsebene beschreibt unser Beitrag zur WordPress-Sicherheit.

Lockfiles committen und wirklich prüfen

Die erste Maßnahme kostet nichts und wird trotzdem regelmäßig übersprungen: composer.lock und package-lock.json gehören ins Repository. Ohne Lockfile löst jeder Build die Abhängigkeiten neu auf, und damit ist jeder Build ein anderes Programm. Mit Lockfile ist der Bauplan festgeschrieben — und, was ebenso wichtig ist, jede Änderung daran wird zu einem sichtbaren Diff im Pull Request.

Daraus folgt die Trennung der Befehle. composer install und npm ci installieren exakt das, was im Lockfile steht. composer update und npm install dürfen Versionen anheben und das Lockfile schreiben. Der erste Satz gehört in die Pipeline, der zweite auf eine Entwicklermaschine und in einen bewussten Pull Request.

Terminal
$ composer install --no-scripts --no-plugins
Installing dependencies from lock file (including require-dev)
$ npm ci --ignore-scripts
added 1284 packages in 9s
$ git diff --stat main -- composer.lock package-lock.json
composer.lock | 41 ++++++++------- package-lock.json | 96 ++++++++++++++++++--------

Der dritte Befehl ist der eigentliche Kontrollpunkt. Ein Lockfile-Diff, der bei einem Patch-Update eines einzelnen Pakets plötzlich neunzig Zeilen umfasst und Pakete berührt, die niemand angefordert hat, ist ein Signal. CISA empfiehlt genau diesen Blick: Prüfen Sie package-lock.json oder yarn.lock, um betroffene Pakete zu identifizieren — einschließlich jener, die tief im Abhängigkeitsbaum verschachtelt sind — und suchen Sie nach zwischengespeicherten Versionen betroffener Abhängigkeiten in Artefakt-Repositories und Werkzeugen zur Abhängigkeitsverwaltung (CISA).

  • composer.lock und package-lock.json sind versioniert, nicht in .gitignore.
  • Die CI verwendet ausschließlich install-Befehle, kein update.
  • Lockfile-Änderungen sind reviewpflichtig und werden nicht automatisch gemergt.
  • Der Cache in Artefakt-Repositories wird bei einem Vorfall mitgeprüft (CISA).
  • Automatische Update-Bots öffnen Pull Requests, sie mergen nicht selbst.

Skript-Kontrolle: --ignore-scripts als Default

Wenn der Payload in preinstall liegt, ist die naheliegendste Gegenmaßnahme, Skripte gar nicht erst laufen zu lassen. Genau das empfehlen die Behörden. In der Aufarbeitung der npm-Kompromittierung heißt es unmissverständlich: Deaktivieren Sie npm-postinstall-Skripte in der CI, wo das möglich ist (CISA). Microsoft nennt als erste Maßnahme in der Analyse der Mai-2026-Welle schlicht npm install --ignore-scripts (Microsoft Security).

Terminal
$ npm config set ignore-scripts true
$ cat .npmrc
ignore-scripts=true min-release-age=7
$ composer install --no-scripts --no-plugins
Generating optimized autoload files

Der ehrliche Teil: Die Empfehlung ist nicht kostenlos. Manche Pakete brauchen ihren Build-Schritt wirklich, etwa nativ kompilierte Module. Der pragmatische Weg ist deshalb kein pauschales Verbot, sondern eine Umkehr der Beweislast: Skripte sind standardmäßig aus, und wo ein Paket sie braucht, wird es namentlich freigegeben und dokumentiert. Aus einer stillen Erlaubnis für tausend Pakete wird eine bewusste Erlaubnis für drei.

Skript-Sperren decken nicht alles ab

--no-scripts verhindert Composer-Lifecycle-Skripte, nicht aber Code, der über autoload.files geladen wird — der Weg, den der laravel-lang-Angriff nutzte (The Hacker News). Bei npm greift --ignore-scripts gegen preinstall und postinstall, nicht gegen Schadcode, der bei der ersten Verwendung des Moduls im Anwendungscode ausgeführt wird. Skript-Kontrolle ist eine wirksame Schicht, keine vollständige Grenze.

Versions-Pinning und das Cooldown-Fenster

Pinning bedeutet, exakte Versionen festzuschreiben statt Bereiche wie ^4.2.0 zu erlauben. CISA formuliert das für den konkreten Vorfall sehr direkt: Pinnen Sie npm-Paketversionen auf bekannt sichere Releases, die vor dem 16. September 2025 erstellt wurden (CISA). Pinning ist wirksam, hat aber die im laravel-lang-Fall gezeigte Grenze — wenn Tags umgeschrieben werden, zeigt dieselbe Versionsnummer auf anderen Code (The Hacker News). Deshalb ist die von Packagist eingeführte Unveränderlichkeit stabiler Versionen so relevant (Packagist).

Die zweite, aus unserer Sicht wirksamste und am meisten unterschätzte Maßnahme ist das Cooldown-Fenster: Neue Versionen werden schlicht eine Weile nicht übernommen. Die Logik dahinter ist einfach — bösartige Versionen werden typischerweise innerhalb von Stunden entdeckt und zurückgezogen, während der Angriff darauf angewiesen ist, dass automatisierte Pipelines sie sofort konsumieren. Wer eine Woche wartet, ist bei den meisten dieser Kampagnen schlicht nicht dabei.

Das ist inzwischen eine Einstellung, kein Konzept. Die npm-CLI führte in Version 11.10.0 (npm CLI), veröffentlicht am 10. Februar 2026, die Option min-release-age ein. Sie nimmt eine Zahl in Tagen und filtert alle Versionen heraus, die jünger sind (npm CLI). Packagist plant eine entsprechende Minimum-Release-Age-Richtlinie, die Installationen von Versionen ablehnt, die vor weniger als einer definierten Zeitspanne veröffentlicht wurden (Packagist).

.npmrc
# Skripte grundsätzlich aus
ignore-scripts=true

# Keine Version installieren, die jünger als 7 Tage ist
min-release-age=7

# Nur die interne Registry als Quelle
registry=https://npm.intern.example.com/
MaßnahmeWirkt gegen preinstallWirkt gegen Tag-RewriteAufwand
Lockfile committenTeilweiseJa, per Hash-PrüfungSehr gering
--ignore-scriptsJaNeinGering bis mittel
Versions-PinningTeilweiseNeinGering
Cooldown-FensterJaJaSehr gering
Registry-ProxyJa, bei FreigabeJaMittel

Der Einwand liegt auf der Hand: Was ist mit dringenden Sicherheitsupdates? Ein Cooldown braucht eine bewusste Ausnahme — ein kritischer Patch wird manuell und begründet vorgezogen. Das kostet ein paar Minuten, ein paar Mal im Jahr, und ist ein guter Tausch gegen ein Zeitfenster, in dem Pipelines jede frisch veröffentlichte Version blind einsammeln.

Registry-Proxy und SBOM: wissen, was hereinkommt

Ein interner Registry-Proxy ist die Stelle, an der aus Vertrauen eine Entscheidung wird. Statt direkt gegen die öffentliche Registry zu ziehen, holt jeder Runner Pakete aus einem internen Spiegel. Der Proxy kann Versionen zurückhalten, Freigaben erzwingen und gemeldete Pakete sofort ökosystemweit blockieren — und er beantwortet die Frage, die in jedem Vorfall zuerst kommt: Was haben wir in den letzten Wochen eigentlich gezogen?

Die zweite Hälfte dieser Antwort ist die SBOM, die Software-Stückliste. Das BSI hat mit der Technischen Richtlinie TR-03183-2 (BSI) formelle und fachliche Vorgaben für Software-Stücklisten definiert. Eine SBOM dokumentiert, welche kommerziellen und freien Software-Bestandteile in Software-Produkten enthalten sind, macht Abhängigkeiten zu Komponenten Dritter transparent und hilft Herstellern, Sicherheitsforschenden sowie professionellen Anwendern beim Monitoring von Schwachstellen (BSI). Das BSI ordnet SBOMs außerdem als zentrale Forderung des europäischen Cyber Resilience Act ein (BSI) — was das regulatorisch bedeutet, ordnet unser Beitrag zu den Pflichten aus dem Cyber Resilience Act ein.

Der praktische Wert zeigt sich im Ernstfall. Microsoft beschreibt für die Erkennung von Shai-Hulud-2.0-Paketen genau dieses Verfahren: Im Hintergrund wird eine SBOM erzeugt und geprüft, ob ein Paket im Dateisystem oder Repository ein bekanntes Schadpaket ist (Microsoft Security). Ohne Stückliste ist Sind wir betroffen? eine mehrtägige Suche. Mit Stückliste eine Abfrage.

  • SBOM pro Build erzeugen, nicht einmalig pro Jahr. Eine Stückliste, die den letzten Release nicht abbildet, beantwortet die falsche Frage.
  • Formate nach TR-03183-2 wählen, damit die Stückliste maschinenlesbar bleibt und für CRA-Nachweise taugt (BSI).
  • Build-Artefakte aufbewahren und der SBOM zuordnen, damit sich im Vorfall exakt sagen lässt, welches Deployment betroffen ist.
  • Interne Registry als einzige Quelle in .npmrc und composer.json konfigurieren, sonst ist der Proxy nur eine Empfehlung.
  • Meldungen automatisiert einspielen, damit ein als bösartig markiertes Paket den nächsten Build stoppt statt eine E-Mail zu erzeugen.

Least-Privilege-Tokens und kurzlebige CI-Secrets

Wenn Sie akzeptieren, dass Schadcode in Ihrer Pipeline laufen kann, lautet die Frage nicht mehr Wie halte ich ihn draußen?, sondern Was findet er vor? Der Payload stiehlt keine Rechte, die nicht da sind: Jeder Token, der nicht in der Umgebung liegt, kann nicht abfließen.

Die Registries haben diesen Schluss selbst gezogen. Am 9. Dezember 2025 widerrief npm alle klassischen Tokens dauerhaft — sie können sich nicht mehr authentifizieren, nicht neu erstellt und nicht wiederhergestellt werden (GitHub Changelog). npm login erzeugt seither Session-Tokens mit zwei Stunden Gültigkeit, granulare Schreib-Tokens sind auf maximal 90 Tage (GitHub Changelog) begrenzt, und für das Veröffentlichen wird OIDC-basiertes Trusted Publishing empfohlen, das Token-Verwaltung überflüssig macht (GitHub Changelog).

Für Ihre Pipeline gilt dieselbe Logik. Microsoft empfiehlt ausdrücklich, unnötige Rollen und Berechtigungen von Identitäten zu entfernen, die CI/CD-Pipelines zugeordnet sind (Microsoft Security). In der Praxis heißt das eine unbequeme Inventur: Der Runner, der Storefront-Assets baut, braucht keinen Schreibzugriff auf die Produktionsdatenbank, keinen Zahlungs-API-Key und kein Publish-Recht. Meistens hat er alles drei, weil irgendwann ein Job das brauchte.

  • Trennen Sie Build und Deploy. Der Job, der fremden Code ausführt, deployt nicht. Der Job, der deployt, führt keinen fremden Code aus.
  • Keine Publish-Rechte im Standard-Build. Ein Token ohne Publish-Recht kann den Wurm nicht weitertragen — genau der Mechanismus, der Shai-Hulud groß gemacht hat (Unit 42).
  • Kurzlebige Credentials statt gespeicherter Schlüssel. OIDC-Verfahren erzeugen Zugangsdaten für die Laufzeit eines Jobs; ein exfiltrierter Token ist danach wertlos.
  • Metadaten-Endpunkte absichern. Der Payload fragt AWS IMDS und Secrets Manager gezielt ab (Microsoft Security).
  • Secrets nicht als Umgebungsvariablen breitflächig setzen, sondern je Schritt gezielt injizieren. Die Umgebung ist das Erste, was durchsucht wird (CISA).
  • Phishing-resistente MFA auf allen Entwicklerkonten, insbesondere bei den Registries (CISA).

Wer das konsequent zu Ende denkt, landet beim selben Prinzip, das wir für Netzwerk und Laufzeit in Zero Trust für Online-Shops beschreiben: kein impliziter Vertrauensvorschuss, auch nicht für den eigenen Build-Runner. Wie sich das in einer konkreten Cloud-Infrastruktur abbilden lässt, hängt von der Plattform ab, das Prinzip bleibt gleich.

Incident-Runbook: was in den ersten Stunden zählt

Wenn eine Meldung wie die zu Shai-Hulud erscheint, zählt Zeit. Die folgenden Schritte fassen zusammen, was CISA, Unit 42 und Microsoft übereinstimmend empfehlen — in der Reihenfolge ihrer Wirkung.

  1. Betroffene Pakete suchen und entfernen. Über alle Endpunkte hinweg nach den gemeldeten Paketen und Versionen scannen und Fundstücke entfernen (CISA).
  2. Alle Zugangsdaten rotieren, sofort. npm-Tokens, GitHub-PATs, SSH-Schlüssel und Cloud-Zugangsschlüssel der betroffenen Entwickler und Runner (Unit 42). Rotieren Sie das, was der Prozess lesen konnte, nicht das, was Sie für betroffen halten.
  3. Build-Artefakte verwerfen. Jedes Artefakt aus einem Build, der eine kompromittierte Version gezogen haben könnte, gilt als unbrauchbar. Caches in Artefakt-Repositories und Abhängigkeits-Werkzeugen gehören dazu (CISA).
  4. Betroffene CI-Agenten isolieren statt sie weiterlaufen zu lassen (Microsoft Security).
  5. Repositories prüfen. Nach unbekannten Repositories, unerwarteten Branches und auffälligen Commits suchen — der Wurm legt eigene Repositories an (Unit 42).
  6. Zugriffslogs der Secret-Stores auswerten, etwa Key-Vault-Zugriffe, um Abflüsse zeitlich einzugrenzen (Microsoft Security).
  7. Updates einfrieren, bis das Bild klar ist (CISA).
  8. Deployments verifizieren. Aus geprüften Quellen neu bauen und gegen das erwartete Lockfile abgleichen, bevor wieder ausgeliefert wird.
Der teuerste Fehler im Vorfall

Zu eng zu rotieren. Der laravel-lang-Stealer sammelte Cloud-Schlüssel, Datenbank- und Queue-Zugangsdaten, Drittanbieter-API-Tokens, OAuth-Client-Secrets, SSH- und Signaturschlüssel sowie Vault- und Kubernetes-Tokens (The Hacker News). Der Payload lief mit den Rechten des PHP-Prozesses. Zu rotieren ist deshalb alles, was dieser Prozess lesen konnte — auch das, was mit dem Paket nichts zu tun hatte.

Der letzte Punkt wird gern übersprungen, weil er nach Formsache klingt. Er ist es nicht: Wenn ein Build kompromittiert war, ist das ausgelieferte Artefakt der eigentliche Schaden — es läuft in Produktion und spricht mit Ihren Kunden. Ein sauberer Neubau aus geprüften Quellen, abgeglichen gegen das erwartete Lockfile, ist der Punkt, an dem ein Vorfall endet.

Die Lieferkette gehört in Ihre Verantwortung

Es gibt keine Maßnahme, die alles abdeckt. Was es gibt, ist eine Reihe billiger Entscheidungen mit hoher Wirkung: Lockfiles committen und ihre Diffs lesen, Skripte standardmäßig ausschalten, ein Cooldown-Fenster setzen, Tokens kurzlebig und ohne Publish-Recht halten, wissen, was gebaut wurde. Zusammengenommen verwandeln sie einen automatischen Angriffsweg in einen, der mehrere bewusste Fehlentscheidungen braucht.

Der Aufwand verteilt sich ungleich: Ein Cooldown und ignore-scripts=true sind zwei Zeilen in einer Konfigurationsdatei, ein Registry-Proxy mit SBOM-Erzeugung und Rechte-Inventur ist ein Projekt. Erfahrungsgemäß lohnt es sich, in dieser Reihenfolge vorzugehen: erst die Zeilen, die heute wirken, dann die Struktur dahinter (Projekterfahrung).

Es geht dabei nicht nur um Abwehr. Eine Build-Kette, in der jede Abhängigkeit bewusst übernommen wird, ist auch die, in der Sie schneller ausliefern — weil niemand raten muss, was ein Update mitgebracht hat. Dieselbe Disziplin trägt bei der Migration von Shopware-Plugins auf 6.7, beim Tuning der Shop-Suche mit OpenSearch und bei rechtlich heiklen Features wie der Auszeichnung von Streichpreisen nach PAngV, wo eine unbemerkte Frontend-Änderung zum Abmahnrisiko wird.

XICTRON härtet Build-Pipelines und Dependency-Prozesse in Kundenprojekten: Skript-Kontrolle und Cooldown-Fenster als Standard, Rechte-Inventur der CI, SBOM pro Build und ein Runbook, das im Vorfall trägt. Wenn Sie nicht sicher sind, was Ihr Runner heute darf, ist das ein guter Startpunkt für ein Gespräch über Ihre Entwicklungsprozesse. Dasselbe Prinzip bei anderem Einfallstor zeigt unser Beitrag zum Absichern von KI-Features im Shop.

Quellen und Studien

Dieser Artikel basiert auf: CISA, Alert: Widespread Supply Chain Compromise Impacting npm Ecosystem, 23.09.2025 (cisa.gov/news-events/alerts/2025/09/23/widespread-supply-chain-compromise-impacting-npm-ecosystem), Microsoft Security Blog, Shai-Hulud 2.0: Guidance for detecting, investigating, and defending against the supply chain attack, 09.12.2025, sowie Mini Shai-Hulud: Compromised @antv npm packages enable CI/CD credential theft, 20.05.2026 (microsoft.com/en-us/security/blog), Palo Alto Networks Unit 42, Shai-Hulud Worm Compromises npm Ecosystem in Supply Chain Attack (unit42.paloaltonetworks.com/npm-supply-chain-attack), BSI, Die Lage der IT-Sicherheit in Deutschland 2025 (Berichtszeitraum 01.07.2024 bis 30.06.2025) sowie BSI, Technische Richtlinie TR-03183-2, Cyber-Resilienz-Anforderungen: Software Bill of Materials (bsi.bund.de), The Hacker News, Berichterstattung zu den npm-, Packagist- und laravel-lang-Vorfällen 2025/2026 (thehackernews.com), Packagist, An update on Composer & Packagist supply chain security (blog.packagist.com) sowie GitHub Changelog und npm CLI, Dokumentation zu Token-Widerruf, granularen Tokens und min-release-age (github.blog, github.com/npm/cli). Ergänzend fließen eigene Projekterfahrungen ein. Die genannten Zahlen können je nach Erhebungszeitpunkt und Methodik variieren.

Häufig gestellte Fragen

Als alleinige Maßnahme in der Regel nicht. Ein Lockfile friert den Bauplan ein und macht Änderungen im Pull Request sichtbar — das ist die Grundlage. Es schützt aber nicht in dem Moment, in dem Sie das Lockfile bewusst aktualisieren, und es schützt nicht gegen Skripte, die beim Installieren der festgeschriebenen Version laufen. Erfahrungsgemäß trägt erst die Kombination aus Lockfile, Skript-Kontrolle und einem Cooldown-Fenster, weil sie unterschiedliche Stellen der Kette abdeckt.

Typischerweise ja, mit Ausnahmen. Die meisten Pakete in einem Storefront-Stack brauchen ihren Lifecycle-Hook nicht; problematisch sind vor allem nativ kompilierte Module. Der übliche Weg ist deshalb, Skripte standardmäßig zu deaktivieren und einzelne Pakete namentlich freizugeben. CISA empfiehlt, npm-postinstall-Skripte in der CI zu deaktivieren, wo das möglich ist (CISA); Microsoft nennt npm install --ignore-scripts als erste Maßnahme (Microsoft Security). Beide formulieren das als Regelfall mit begründeten Ausnahmen, nicht als Alles-oder-nichts.

Das hängt von Ihrer Release-Frequenz ab. Die npm-CLI unterstützt seit Version 11.10.0 die Option min-release-age in Tagen (npm CLI). In der Praxis bewegen sich viele Teams zwischen einem und sieben Tagen: Ein Tag fängt bereits einen großen Teil der schnellen Kampagnen ab, weil bösartige Versionen typischerweise binnen Stunden entdeckt und zurückgezogen werden; sieben Tage geben zusätzliche Sicherheit, verzögern aber auch reguläre Updates. Wichtig ist in beiden Fällen ein definierter Weg, um einen kritischen Sicherheitspatch begründet vorzuziehen.

Ja. Der laravel-lang-Vorfall im Mai 2026 lief vollständig über Composer: Über 700 Versionen von vier Paketen wurden über umgeschriebene Git-Tags kompromittiert, der Payload hing im Autoloader und lief bei jedem PHP-Request (The Hacker News). Hinzu kommt, dass moderne Storefronts selten wirklich npm-frei sind — in einer weiteren Kampagne platzierten Angreifer den Schadcode bei acht Packagist-Paketen gezielt in der package.json, weil viele PHP-Projekte JavaScript-Build-Werkzeuge mitliefern (The Hacker News).

Zuverlässig nur mit Aufzeichnungen, die vor dem Vorfall entstanden sind. CISA empfiehlt, package-lock.json beziehungsweise yarn.lock auf betroffene Pakete zu prüfen, einschließlich tief verschachtelter Abhängigkeiten, und zusätzlich zwischengespeicherte Versionen in Artefakt-Repositories zu durchsuchen (CISA). Microsoft beschreibt für die Erkennung das Erzeugen einer SBOM mit anschließendem Abgleich gegen bekannte Schadpakete (Microsoft Security). Ohne Lockfile-Historie und ohne Stückliste bleibt in der Regel nur eine aufwendige manuelle Rekonstruktion.

Erfahrungsgemäß mehr, als zunächst angenommen wird. Maßstab ist nicht das kompromittierte Paket, sondern der Prozess, in dem es lief: alles, was dieser Prozess lesen konnte. Unit 42 nennt npm-Tokens, GitHub-PATs, SSH-Schlüssel und Cloud-Zugangsschlüssel (Unit 42); beim laravel-lang-Stealer kamen Datenbank-, Queue- und Cache-Zugangsdaten, Drittanbieter-Tokens, OAuth-Client-Secrets, Signaturschlüssel sowie Vault- und Kubernetes-Tokens hinzu (The Hacker News). Parallel dazu gehören Build-Artefakte aus dem fraglichen Zeitraum verworfen und betroffene CI-Agenten isoliert (Microsoft Security).