Im Juni 2026 deckten Sicherheitsforscher eine weitere Weiterentwicklung der Malware-Familie Mini Shai-Hulud auf, die den Namen Miasma erhielt. Anders als klassische npm-Malware, die es auf eine Handvoll Pakete abgesehen hat, zeigte diese Kampagne, wie schnell sich die Kompromittierung eines einzelnen Bausteins der Entwickler-Infrastruktur über mehrere Ökosysteme ausbreiten kann: npm, GitHub Actions und sogar Go-Module.
Die Angreifer zielten nicht auf Endanwender. Sie zielten auf Publisher, auf CI/CD-Pipelines und auf die Vertrauensmechanismen, die es Software erlauben, vom Laptop eines Entwicklers bis in die Produktion zu gelangen, ohne dass jemand sie unterwegs noch einmal prüft. Für nichts davon existiert eine CVE, denn am betroffenen Code war nie etwas fehlerhaft. Der Einstiegspunkt war ein gestohlenes Zugangsdatum, keine Schwachstelle.
Eines sollte man gleich vorweg festhalten: Am 12. Mai 2026 veröffentlichte die Gruppe, die ursprünglich hinter dieser Wurm-Familie stand, TeamPCP, den vollständigen Quellcode von Shai-Hulud/Mini Shai-Hulud öffentlich auf GitHub unter MIT-Lizenz. Das verändert, wie diese Geschichte zu lesen ist. Die vier darauffolgenden Wellen teilen sich dasselbe Toolkit und dieselben Techniken, aber gemeinsames Werkzeug bedeutet inzwischen nicht mehr denselben Betreiber. Sobald das Framework öffentlich ist, kann jeder technisch versierte Akteur eine Kampagne fahren, die von der von TeamPCP nicht zu unterscheiden ist. Das Folgende ist daher als Überschneidung von Taktiken, Techniken und Prozeduren (TTPs) zu lesen, nicht als gesicherte Zuordnung zu einer einzelnen Gruppe.
Betroffene Pakete (npm und Go)
| Paket | Kompromittierte Version |
|---|---|
hexo-deployer-wrangler | 1.0.4 |
hexo-shoka-swiper | 0.1.10 |
leo-auth | 4.0.6 |
leo-aws | 2.0.4 |
leo-cache | 1.0.2 |
leo-cdk-lib | 0.0.2 |
leo-cli | 3.0.3 |
leo-config | 1.1.1 |
leo-connector-elasticsearch | 2.0.6 |
leo-connector-mongo | 3.0.8 |
leo-connector-mysql | 3.0.3 |
leo-connector-oracle | 2.0.1 |
leo-connector-redshift | 3.0.6 |
leo-cron | 2.0.2 |
leo-logger | 1.0.8 |
leo-sdk | 6.0.19 |
leo-streams | 2.0.1 |
prism-silq | 1.0.1 |
rstreams-metrics | 2.0.2 |
rstreams-shard-util | 1.0.1 |
serverless-convention | 2.0.4 |
serverless-leo | 3.0.14 |
solo-nav | 1.0.1 |
github.com/verana-labs/verana-blockchain (Go) | v0.10.1-dev.20 |
Socket setzt die Untersuchung fort; neue Erkenntnisse werden laufend auf der Miasma-Tracking-Seite ergänzt.
Wenn Ihr Abhängigkeitsbaum eines dieser Pakete in den genannten Versionen enthält (oder Pakete aus früheren kompromittierten Wellen derselben Kampagne von Anfang Juni), behandeln Sie die Umgebung als potenziell kompromittiert und folgen Sie den unten beschriebenen Sofortmaßnahmen.
Zeitlicher Ablauf
24. Juni 2026
↓
Maintainer-Konto von LeoPlatform kompromittiert
↓
23 bösartige Paketversionen veröffentlicht (im Sekundenabstand)
↓
binding.gyp-Payload wird bei der Installation ausgeführt
↓
Zugangsdaten von Entwicklern und CI/CD gestohlen
↓
GitHub-Actions-Workflow („Run Copilot“) eingeschleust
↓
Gestohlene Secrets in öffentliche GitHub-Repositories exfiltriert
↓
Go-Modul (Verana Blockchain) über eine verwandte Technik kompromittiert
↓
Forscher bei Socket, Wiz, Sonatype und anderen identifizieren die Kampagne und legen sie offen
Das ist die vierte Welle derselben Kampagnenfamilie in weniger als einem Monat: Sie trat zuerst am 1. Juni gegen den npm-Namespace von Red Hat in Erscheinung, dann folgte am 3. Juni eine Welle mit 57 Paketen und schließlich am 24.–25. Juni diese LeoPlatform/Go-Welle. Wie oben erwähnt hat TeamPCP das zugrunde liegende Wurm-Framework am 12. Mai als Open Source veröffentlicht, sodass „dieselbe Kampagnenfamilie“ hier gemeinsame TTPs über diese Wellen hinweg beschreibt und keinen gesicherten Nachweis, dass ein einzelner Betreiber hinter allen vier steckt.
Was tatsächlich passiert ist
- Einem Maintainer des LeoPlatform-npm-Ökosystems wurden die Kontozugangsdaten oder das npm-Token gestohlen, höchstwahrscheinlich durch einen Infostealer.
- Mit diesem gestohlenen Zugang veröffentlichte der Angreifer trojanisierte Versionen von Paketen, die der Maintainer bereits rechtmäßig besaß. Nichts musste im klassischen Sinn „gehackt“ werden, denn der Angreifer verfügte bereits über eine vertrauenswürdige Publishing-Identität.
- Wer eine dieser Versionen installierte, führte eine versteckte Payload aus, die die eigenen Zugangsdaten abgriff.
- Ein Teil dieser gestohlenen Zugangsdaten gehörte zu GitHub-Actions-Umgebungen, was dem Angreifer erlaubte, einen bösartigen Workflow zu platzieren und CI/CD-Secrets direkt aus dem Runner abzuziehen.
- Unabhängig davon wurde ein Go-Modul mit einer verwandten, aber eigenständigen Technik kompromittiert, was zeigt, dass die Kampagne an keine bestimmte Sprache und keinen bestimmten Paketmanager gebunden ist.
- Aufgedeckt wurde das Ganze, weil mehrere unabhängige Security-Research-Teams aus früheren Wellen derselben Kampagne heraus genau auf dieses Muster achteten.
Technische Analyse
Stufe 1: Kompromittierter Maintainer
Das npm-Konto czirker, das zu LeoPlatform gehört, wurde kompromittiert, höchstwahrscheinlich über geleakte Zugangsdaten oder ein Token, das ein bereits auf dem Rechner des Maintainers laufender Infostealer abgegriffen hat.
Stufe 2: Veröffentlichung der bösartigen Pakete
Mit dem gestohlenen Token veröffentlichte der Angreifer innerhalb eines Zeitfensters von sechs Sekunden 23 bösartige Paketversionen quer durch die Ökosysteme LeoPlatform und RStreams. Diese Geschwindigkeit deutet auf ein skriptgesteuertes, automatisiertes Publishing-Tool hin, nicht auf einen Menschen, der Dateien von Hand hochlädt.
Das konkreteste Detail der gesamten Kampagne steckt in dieser Stufe: Der Angreifer veröffentlichte nicht nur bösartige Versionen, sondern setzte auch den latest-Dist-Tag von leo-sdk auf die vergiftete 6.0.19 um, während das saubere Release 7.1.21 nur noch unter dem weniger sichtbaren Tag awsv3 verfügbar blieb. In der Praxis bedeutet das: Jede Umgebung, die npm install leo-sdk ohne expliziten Semver-Pin ausführte, wurde aktiv zum Wurm gelenkt, obwohl die ganze Zeit ein sauberes Release existierte. Die praktische Lehre ist unmissverständlich: Das Pinnen der Version, nicht des Tags, war der tatsächliche Unterschied zwischen einer sauberen Installation und einer Kompromittierung.
Stufe 3: Ausführung zur Installationszeit
Hier liegt der raffinierte Teil. Die meisten bösartigen npm-Pakete werden entdeckt, weil Scanner die Skriptfelder preinstall und postinstall in der package.json überwachen. Miasma lässt diese komplett aus und legt stattdessen eine binding.gyp-Datei ab, also die Konfiguration, mit der Node.js native Module während der Installation kompiliert. Weil binding.gyp ein völlig normaler Bestandteil beim Bauen nativer Add-ons ist, führt sie während npm install Code aus, ohne je die Felder anzufassen, auf die die meisten Werkzeuge achten.
Gegen diese Technik gab es zwei echte Gegenmaßnahmen, und bei beiden lohnt sich Präzision. Die erste existierte bereits: npm install --ignore-scripts unterdrückt laut npm-Dokumentation tatsächlich den impliziten node-gyp rebuild-Hook, den eine binding.gyp-Datei auslöst. Für sich allein ist das keine vollständige Verteidigung, denn ein bösartiges Paket kann trotzdem heruntergeladen und entpackt werden, und ein späterer Rebuild ohne dieses Flag kann den Hook weiterhin auslösen, aber diesen konkreten Ausführungspfad blockiert es. Die zweite Gegenmaßnahme kam drei Wochen zu spät: npm v12, ausgeliefert im Juli 2026, schließt diesen Vektor standardmäßig und behandelt den durch binding.gyp ausgelösten impliziten node-gyp rebuild genau wie jedes andere Install-Skript, also blockiert, sofern das Paket nicht explizit auf einer Allowlist steht. Miasmas „Phantom Gyp“-Technik war im Grunde ein gezielter Angriff auf genau die Lücke, für deren Schließung npm v12 gebaut wurde.
Stufe 4: Sammeln von Secrets
Einmal gestartet, sammelt die Payload ein breites Spektrum an Zugangsdaten ein, darunter:
- npm- und PyPI-Tokens
- GitHub Personal Access Tokens und GitHub-OIDC-Tokens
- Zugangsdaten für AWS, Azure und GCP
- SSH-Schlüssel
- Konfigurations- und Credential-Pfade von Claude Code, Cursor und anderen KI-Coding-Assistenten
- OpenAI-API-Keys
- Slack- und Twilio-Tokens, Docker-Auth-Dateien, Kubernetes-Konfigurationen, Vault-Daten und Shell-History
Stufe 5: Missbrauch von GitHub
Die Malware legt einen GitHub-Actions-Workflow ab (beobachtet unter dem Namen „Run Copilot“), der Secrets während der Ausführung direkt aus dem Speicher des CI-Runners zieht. Die gestohlenen Daten werden verschlüsselt und in neu angelegte öffentliche GitHub-Repositories gepusht, die als tote Briefkästen dienen; zum Zeitpunkt der Veröffentlichung tragen mehr als 550 Repositories die Exfiltrationsmarkierung der Kampagne. Bei einem verwandten Vorfall am selben Tag erzwang ein Angreifer per Force-Push einen bösartigen Commit in eine weit verbreitete GitHub Action und ließ die Versions-Tags darauf zeigen. Jeder Workflow, der danach gegen diese Tags lief, führte damit die Payload des Angreifers direkt im GitHub-Actions-Runner aus.
Stufe 6: Verbreitung
Entwicklerrechner kompromittiert
↓
GitHub-Zugangsdaten des Entwicklers gestohlen
↓
CI/CD-Pipeline-Secrets aus dem Runner abgegriffen
↓
Gestohlenes npm-Token zur Veröffentlichung weiterer bösartiger Pakete genutzt
↓
Weitere Entwickler installieren die kompromittierten Pakete
↓
(und wieder von vorn)
Jede erfolgreiche Kompromittierung wird zur Startrampe für die nächste. Genau das macht aus der Sache eine selbstverbreitende Kampagne statt eines einzelnen Vorfalls.
Warum dieser Angriff anders ist
| Klassische Supply-Chain-Angriffe | Miasma |
|---|---|
| Einzelnes Paket | Gesamtes Ökosystem |
| Diebstahl von Kryptowährung | Breit angelegter Diebstahl von Zugangsdaten |
| Eine Sprache | Mehrere Sprachen (npm, jetzt auch Go) |
| Ein Maintainer | Entwickler-Infrastruktur als Ganzes |
| Statische Malware | Selbstverbreitend, von Welle zu Welle weiterentwickelt |
Frühere npm-Supply-Chain-Vorfälle waren überwiegend Blitzaktionen: ein Paket kompromittieren, Wallet-Schlüssel oder Session-Tokens stehlen, weiterziehen. Miasma verhält sich eher wie ein Wurm mit Geschäftsmodell. Er behandelt jede erfolgreiche Infektion als Treibstoff für die nächste Welle, und er entwickelt sich nachweislich weiter, mehr als drei Wochen und vier separate Wellen später.
Warum GitHub Actions zum Ziel wurde
GitHub Actions sitzt an einer besonders wertvollen Stelle der Software-Lieferkette: Es hält OIDC-Tokens für vertrauenswürdiges Publishing ohne hinterlegte Zugangsdaten zu Cloud-Anbietern und Registries, es speichert langlebige CI-Secrets, und es ist per Design auf automatisierte, unbeaufsichtigte Ausführung ausgelegt. Wer einen CI-Runner kompromittiert, legt nicht nur den Laptop eines einzelnen Entwicklers offen, sondern jede Deployment-Pipeline, jeden Registry-Publish und jedes Cloud-Zugangsdatum, das dieser Workflow berührt. Das ist ein weit größerer Wirkungsradius als die lokale Umgebung eines einzelnen Entwicklers, und genau deshalb hat die Kampagne eigene Werkzeuge gebaut, um gezielt darauf loszugehen.
Warum die Ausweitung auf Go wichtig ist
Der Großteil der Berichterstattung zu dieser Kampagne konzentrierte sich auf npm, weil dort die meisten Pakete liegen. Die Kompromittierung des Go-Moduls ist aber wohl das wichtigste Detail der gesamten Geschichte, und es ist dasjenige, das die meisten Analysen überspringen.
Das Go-Sample verwendet keine binding.gyp. Es stützt sich überhaupt nicht auf die Modulauflösung oder die Build-Mechanismen von Go. Stattdessen kann ein Entwickler, der das Repository einfach klont oder es in einer vertrauten IDE oder einem KI-Coding-Assistenten öffnet, die Payload allein über die Projektkonfiguration auslösen.
Das sagt etwas Wichtiges: Die Angreifer interessieren sich im Kern nicht für JavaScript, nicht für npm und nicht für die Mechanik eines bestimmten Paketmanagers. Sie interessieren sich für Entwickler, und zwar überall dort, wo Entwickler automatisierten Werkzeugen vertrauen, sei es ein Install-Skript, ein Build-Schritt oder eine IDE, die einen Ordner öffnet. Die Sprache spielt keine Rolle. Die Zugangsdaten der Entwickler schon.
Die größere Lektion
Altes Denken:
Wir scannen Abhängigkeiten
↓
Wir patchen bekannte CVEs
↓
Wir sind sicher
Heutige Realität:
Ein Entwickler wird kompromittiert
↓
CI/CD wird kompromittiert
↓
Ein legitimes Paket wird mit bösartigem Code veröffentlicht
↓
Jeder nachgelagerte Konsument installiert es
↓
An keiner Stelle ist eine CVE erforderlich
Dependency-Scanning beantwortet die Frage „Hat dieser Code eine bekannte Schwachstelle?“. Miasma legt eine völlig andere Frage offen, auf die die meisten Sicherheitsprogramme überhaupt nicht eingerichtet sind: „Vertraue ich den Menschen und automatisierten Systemen, die Code in meine Umgebung veröffentlichen dürfen, und zwar jetzt, heute?“
Erkennungsmöglichkeiten
Statt „Wie hält man das auf?“ ist die nützlichere Frage, wo ein Verteidiger realistisch die Chance hatte zu bemerken, dass etwas nicht stimmt. An dieser Stelle hört die meiste Berichterstattung zu Miasma auf, deshalb lohnt es sich, hier tiefer einzusteigen.
Publish-Geschwindigkeit. 23 Paketversionen in einem Zeitfenster von sechs Sekunden zu veröffentlichen, ist nichts, was ein Mensch tut. Jede Organisation, die einen eigenen npm-Registry-Mirror betreibt oder die öffentlichen Registry-Events für Pakete beobachtet, von denen sie abhängt, könnte solche Publish-Bursts automatisch markieren. Ein einzelner Versionssprung ist normal. Zwei Dutzend in wenigen Sekunden sind für sich genommen ein Signal, unabhängig davon, was das Paket tatsächlich enthält.
Dist-Tag-Änderungen ohne einen von Nutzern gewünschten Versionssprung. Der leo-sdk-Hijack funktionierte genau deshalb, weil latest auf eine niedrigere, älter wirkende Versionsnummer (6.0.19) wanderte, während ein neueres sauberes Release (7.1.21) unter einem anderen Tag lag. Jedes Werkzeug, das die Dist-Tags eines Pakets über die Zeit vergleicht und nicht nur seine Versionsliste, hätte erkannt, dass latest in der Versionsfolge rückwärts zeigt, was so gut wie nie legitimes Verhalten ist.
Build-Artefakte, die nicht zum Quellcode passen. Das kompromittierte leo-sdk-Paket wuchs von einer 10 KB großen index.js in der sauberen Version auf eine 5 MB große index.js in der vergifteten an, dazu eine binding.gyp-Datei, die nirgends im eigentlichen GitHub-Repository des Projekts existiert. Ein Vergleich dessen, was in der Registry veröffentlicht ist, mit dem, was in der Versionsverwaltung committet ist, Paket für Paket, hätte das sofort zutage gefördert. Die meisten Organisationen führen diesen Vergleich nie durch.
Unerwartete native Builds bei reinen JavaScript-Paketen. leo-sdk ist ein JavaScript-SDK ohne legitimen Bedarf an nativer Kompilierung. Eine binding.gyp, die bei einem Paket auftaucht, das noch nie eine ausgeliefert hat oder das keinen plausiblen Grund dafür hat, ist für sich genommen ein starkes Anomaliesignal, lange bevor jemand prüft, was die Datei tatsächlich tut.
Neue Workflow-Dateien ohne zugehörigen Pull Request. Eine Workflow-Datei namens „Run Copilot“, die in .github/workflows/ auftaucht, ohne verknüpften PR, ohne Review und ohne einen Autor, den jemand kennt, ist genau die Art von Änderung, für deren Erkennung Branch Protection und Pflicht-Reviews existieren, sofern sie speziell für Workflow-Dateien auch tatsächlich durchgesetzt werden.
Ausgehender Traffic zu frisch angelegten GitHub-Repositories. Weil die Exfiltration auf neu angelegten öffentlichen Repositories als tote Briefkästen beruhte, sind CI-Runner oder Entwicklerrechner, die ausgehende API-Aufrufe zum Anlegen neuer Repositories absetzen oder in Repositories pushen, die eine Stunde zuvor noch nicht existierten, ein erkennbares und ziemlich ungewöhnliches Verhaltensmuster.
OIDC- und Token-Nutzung außerhalb des gewohnten Musters. Ein GitHub-OIDC-Token oder ein npm-Publish-Token, das aus einem IP-Bereich, einem Workflow oder einem Zeitfenster heraus verwendet wird, aus dem es zuvor nie genutzt wurde, ist ein klassisches Identitätsanomalie-Signal, und eines, für dessen Erkennung man nichts über diese konkrete Kampagne wissen muss.
Keiner dieser Ansätze benötigt eine CVE-Datenbank oder Vorwissen speziell über Miasma. Sie erfordern, tatsächlich zu beobachten, wie sich Vertrauen, Publishing-Verhalten und Identitäten im Laufe der Zeit durch Ihre Umgebung bewegen, und nicht nur, was zu einem einzelnen Zeitpunkt in einer Manifest-Datei steht.
Was Organisationen tun sollten
Sofort
- Zugangsdaten für jede Umgebung rotieren, die ein betroffenes Paket installiert hat, aber erst, nachdem die bösartige Version entfernt und sichergestellt ist, dass keine Persistenz mehr besteht, nicht davor.
- Betroffene Paketversionen in Lockfiles, Caches, Containern und CI-Runnern aktualisieren oder entfernen, nicht nur im obersten Manifest.
- Alle GitHub-Tokens, OIDC-Konfigurationen und npm-Tokens widerrufen und neu ausstellen, die offengelegt worden sein könnten.
- GitHub Actions per Commit-Hash pinnen statt über veränderliche Versions-Tags.
Mittelfristig
- Paket-Allowlists dafür einführen, was in CI/CD- und Produktions-Builds zugelassen ist.
- Paket-Provenance und Signierung verlangen, wo verfügbar.
- Eine echte Software Bill of Materials (SBOM) pflegen, keinen einmaligen Schnappschuss.
- Eine Karenzzeit einführen, bevor neu veröffentlichten Paketversionen in einem Build vertraut wird.
Langfristig
- Kontinuierliche Validierung dessen, was in Ihrer Umgebung tatsächlich läuft, statt periodischer Audits.
- Überwachung von Repositories und CI/CD auf unerwartete Workflow-Änderungen oder ungewöhnliches Publishing-Verhalten.
- Laufende Angriffspfad-Analyse: nicht nur „Ist dieses Paket verwundbar?“, sondern „Was könnte jemand erreichen, wenn dieses Paket bösartig wäre?“.
- Überwachung von Entwickler-Identitäten, denn in dieser Kampagne war die Identität die eigentliche Angriffsfläche.
Warum das für Penetrify wichtig ist
Miasma war kein npm-Problem. Es war ein Identitätsproblem. Ein CI/CD-Problem. Ein Vertrauensproblem. Ein Angriffspfad-Problem.
Die Angreifer haben keine Schwachstelle entdeckt. Sie haben einen Pfad entdeckt, der von der Workstation eines einzelnen Entwicklers zu Tausenden nachgelagerter Systeme führt, und dieser Pfad verlief vollständig innerhalb von Beziehungen, die die meisten Sicherheitsprogramme nie wirklich überwachen: welche Menschen Code veröffentlichen dürfen, welche Tokens ein Deployment auslösen können, welche Workflows unbeaufsichtigt mit echtem Zugriff auf die Produktion laufen.
npm v12 schließt den konkreten Ausführungsvektor, auf den Miasma angewiesen war. Am darunterliegenden Identitätsproblem ändert es nichts. Wie es Moshe Siman Tov Bustan von OX Security in der Berichterstattung zum npm-v12-Rollout formulierte: Sobald ein Angreifer die Zugangsdaten eines legitimen Maintainers kontrolliert, hilft das Blockieren von Install-Skripten nicht mehr, denn der bösartige Code wird als vertrauenswürdiges, signiertes Release ausgeliefert.
Das ist das gesamte Argument dieses Artikels, einfacher formuliert, als wir es könnten. Moderne Software-Supply-Chain-Sicherheit muss über Dependency-Scanning hinausgehen und kontinuierlich verstehen, wie sich Vertrauensbeziehungen über Repositories, Build-Pipelines, Identitäten und Produktionsumgebungen hinweg entwickeln, statt nur zu wissen, welche CVEs in einer Manifest-Datei stehen.
Quellen
- The Hacker News: Miasma Malware Targets npm Packages and GitHub Actions in Supply Chain Attack
- Socket: Miasma Mini Shai-Hulud Hits LeoPlatform npm Packages and Go Ecosystem
- StepSecurity: Mass npm Supply Chain Attack: 20 Leo Platform Packages Compromised und Supply Chain Compromise: codfish/semantic-release-action
- Endor Labs: Shai-Hulud Strikes Leo Platform npm
- Corgea: Leo Platform npm packages compromised with Phantom Gyp Miasma toolkit
- Snyk: Node-gyp Supply Chain Compromise
- Datadog Security Labs: Shai-Hulud Goes Open Source
- The Register: Malware crew TeamPCP open-sources its Shai-Hulud worm on GitHub
- GitHub Changelog: Upcoming breaking changes for npm v12
- TechTimes: npm v12 Ships This Month, Blocking Install Scripts That Enabled Year of Supply Chain Attacks
