Der Wurm wurde Open Source
Irgendwann in der Woche des 11. Mai 2026 haben die Leute hinter Shai-Hulud — dem selbstreplizierenden npm-Supply-Chain-Wurm, der seit September 2025 Maintainer-Konten frisst — ihren eigenen Quellcode geleakt. Bis zum Wochenende hatte OX Security vier typosquattete npm-Pakete unter einem Konto gefunden, von denen eines eine fast wortwörtliche Kopie des geleakten Wurms ist, ein weiteres ein Golang-DDoS-Bot, und die anderen beiden schlichte Infostealer, die SSH-Schlüssel und Krypto-Wallets an Schnäppchen-C2s schicken. Die Einstiegshürde für Supply-Chain-Angriffe ist gerade massiv gesunken, und die Personen, die am ehesten eines dieser Pakete installieren, sind keine Menschen mehr.
Irgendwann letzte Woche haben die Leute hinter Shai-Hulud — dem
npm-Wurm, der sich seit September 2025 durch Maintainer-Konten
frisst — ihren eigenen Quellcode geleakt. Bis zum Wochenende
hatte ein npm-Konto namens deadcode09284814 vier Typosquats
veröffentlicht, die diesen Code wiederverwenden. Eines war der
Wurm, fast wortwörtlich. Eines war ein Golang-DDoS-Bot. Zwei
waren schlichte Infostealer, die Ihre SSH-Schlüssel, Ihre
~/.aws/credentials und Ihren MetaMask-Tresor per POST an eine
gemietete IP schicken. Zweitausendsechshundertachtundsiebzig
Installationen später lautet die Frage nicht mehr „wird jemand
den Leak waffenfähig machen". Die Frage lautet, welcher der
Agenten, die heute Nachmittag in Ihrem Terminal npm install
tippen, sich eines davon einfängt.
Es gibt etwas, das in der offensiven Software periodisch passiert:
Ein geschlossenes Tool wird in einem Forum abgekippt, und die
Anzahl der Leute, die es ausführen können, geht von „der einen
Crew, die es geschrieben hat" zu „jedem Teenager mit einem VPS".
Mimikatz. EternalBlue. Contis Quellcode. Jedes Mal hat sich nicht
die Fähigkeit verändert — sie war einfach nicht mehr knapp. Die
Schlagzeile letzte Woche, gemeldet von
BleepingComputer
auf der Grundlage von Recherchen von
OX Security,
lautet: Shai-Hulud — der Wurm, über den wir
geschrieben haben, als er in
sechs Minuten zweiundvierzig @tanstack-Pakete fraß — ist dieser
Liste beigetreten.
Die Fork ist nicht theoretisch. Bis Sonntag hatte OX vier
schädliche Pakete dokumentiert, veröffentlicht von einem einzigen
npm-Konto namens deadcode09284814:
chalk-tempalte— ein Typosquat vonchalk-template, der eine fast wortwörtliche Kopie des geleakten Shai-Hulud-Quellcodes enthält, einschließlich des charakteristischen Shai-Hulud-Verhaltens, gestohlene Anmeldedaten als öffentliche automatisch generierte GitHub-Repositories hochzuladen. OX' Einschätzung: „Der Shai-Hulud-Schadcode ist eine fast exakte Kopie des geleakten Quellcodes, ohne Obfuskationstechniken", was auf einen neuen Bedrohungsakteur hindeutet, der sich nicht einmal die Mühe gemacht hat, die Seriennummern abzuschleifen.axois-utils— ein Typosquat vonaxios-utils, der eine Golang-Payload ausliefert, die OX Phantom Bot nennt: HTTP-, TCP-, UDP- und Reset-Floods, Persistenz über den Windows-Autostart-Ordner und geplante Aufgaben, und ein C2 unterb94b6bcfa27554.lhr.life. Ihre Entwicklermaschine, zwangsrekrutiert.@deadcode09284814/axios-util— ein anderer Typosquat, eine andere Payload: SSH-Schlüssel, Umgebungsvariablen, AWS/GCP/Azure-Anmeldedaten, verschickt an80.200.28.28:2222. „Ziemlich simpel", in OX' Worten.color-style-utils— ein schlichter Infostealer, der Ihre IP, Geolokation und Krypto-Wallet-Daten greift und anedcf8b03c84634.lhr.lifeper POST schickt.
Kombinierte wöchentliche Downloads zum Zeitpunkt von OX' Bericht: 2.678.
Hier sind zwei Geschichten miteinander verwoben, die es verdienen,
auseinandergezogen zu werden. Die langweilige ist, dass npm
Typosquats hat. Das hat es; das hatte es immer; das wird es immer
haben, aus demselben Grund, aus dem es im Hundepark Hunde namens
Bench gibt — Namen sind billig und der Namensraum ist flach. Die
interessante ist, dass die Hürde, einen Wurm der Shai-Hulud-Klasse
zu betreiben, gerade gefallen ist. Bis letzte Woche brauchten Sie
das Werkzeug der ursprünglichen Crew, die Infrastruktur der
ursprünglichen Crew, die Disziplin der ursprünglichen Crew, nicht
erwischt zu werden. Heute brauchen Sie einen GitHub-Klon eines
öffentlichen Repos, einen lhr.life-Tunnel und die Geduld,
npm publish zu tippen. Die vier Pakete, die OX gefunden hat, sind
zusammen der Beweis.
Warum die Anzahl der Akteure wichtiger ist als die Anzahl der Pakete.
Ein einzelner ausgefeilter Wurm ist in gewisser Weise ein
beherrschbarer Gegner. Er hat Tells. Er hat Infrastruktur. Er hat
Gewohnheiten. Erkennungssignaturen lassen sich gegen ihn schreiben.
Aikido, Socket, Snyk, Wiz — die Shops für npm-Supply-Chain-Überwachung,
die beim @tanstack-Vorfall am 11. Mai sofort zur Stelle waren —
haben ihn innerhalb von Stunden erwischt, und zwar gerade deshalb,
weil sie dieselbe Familie acht Monate lang beobachtet hatten.
Eine Familie abgeleiteter Würmer, geschrieben von Leuten, die den
Quellcode von einer Paste-Site heruntergeladen haben, hat eine
andere Form. Jeder einzelne wird zu einem anderen C2 exfiltrieren,
einen anderen RSA-Schlüssel einbetten, eine andere Kombination von
Dateien zum Lesen wählen und einen anderen Typosquat-Raum bewohnen.
Manche werden sorgfältig sein; die meisten werden auf eine Art
schlampig sein, die dazu führt, dass sie schnell erwischt werden;
einer von ihnen, wenn wir das nächste Mal einen Beitrag wie diesen
schreiben, wird ausgefeilt genug sein, dass wir ihn nicht innerhalb
einer Woche erwischen. Das Erkennungsproblem der Verteidiger
weitet sich aus von „Shai-Hulud erkennen" zu „alles erkennen, was
~/.ssh/id_ed25519 aus einem prepare-Skript heraus lesen will".
Das ist eine viel, viel größere Oberfläche.
Auch die Form des Installationspfads hat sich verändert, und genau
das sollte jeden beunruhigen, der einen Coding-Agenten betreibt.
Ein menschlicher Entwickler, der chalk-template wollte, hätte
2024 den Paketnamen aus einem Tutorial gelesen, ihn getippt und den
Tippfehler bemerkt, als chalk-tempalte mit zweihundert Downloads
und einem Fremden als Herausgeber zurückkam. Ein
Coding-Agent, der
2026 gebeten wird, „etwas Farbe zu meiner CLI-Ausgabe hinzuzufügen",
wird installieren, was immer der Paketmanager zurückgibt. Der Agent
sieht das Publisher-Feld nicht. Der Agent bemerkt nicht, dass die
README drei Zeilen lang ist. Der Agent macht in dieser Stunde
dreißig npm installs, weil der Nutzer die Arbeit eines kleinen
Teams erledigt und der Agent pro Aufgabe bezahlt wird, nicht pro
Installation.
Was ein unverschleierter Shai-Hulud-Klon tatsächlich tut.
Das Paket chalk-tempalte ist, schreibt OX, „fast ohne jegliche
Änderung" gegenüber dem geleakten Quellcode. Das bedeutet, dass
dieselben Mechanismen, die wir in
Der Wurm, der sich selbst in .claude schreibt
durchgegangen sind, gelten — mit einer bedeutenden neuen Wendung:
der Exfiltrationskanal ist GitHub selbst.
Shai-Huluds Markenzeichen — vom Nachahmer beibehalten, weil
Kopieren einfacher ist als Umschreiben — besteht darin, dass die
gestohlenen Anmeldedaten nicht an einen versteckten Drop-Server
gehen. Sie gehen in ein frisch erstelltes öffentliches
GitHub-Repository, veröffentlicht mit einem GitHub-Token, das die
Schadsoftware gerade beim Opfer gestohlen hat. Die Geheimnisse des
Opfers sitzen in einem öffentlichen Repo, das dem GitHub-Konto des
Opfers selbst gehört, für jeden auf der Welt zum Abgreifen — bis
jemand es bemerkt und das Repo zerstört wird. Das Standard-Playbook
des Verteidigers — die Exfil-Domain blockieren, nach ungewöhnlichem
ausgehendem DNS suchen — fängt das nicht ab, weil das ausgehende
DNS api.github.com ist, mit dem Ihre Entwicklermaschine ohnehin
zweihundertmal pro Stunde spricht. Das Anmeldedaten-Bundel verlässt
Ihren Laptop verkleidet als git push.
Sobald die Geheimnisse öffentlich sind, kann sie jeder, der den GitHub-Firehose beobachtet — und mehrere Leute beobachten den GitHub-Firehose genau aus diesem Grund — einsammeln. Der Wurm muss seinen C2 nicht am Leben halten. GitHub ist der C2.
In diesem Bild steckt ein winziges Detail, bei dem es sich lohnt
zu verweilen. Der Shai-Hulud-Klon chalk-tempalte ist nicht
einmal auf seine eigene Infrastruktur angewiesen, um die Beute zu
empfangen. Er verwendet die GitHub-Identität des Opfers selbst,
um die gestohlenen Geheimnisse des Opfers selbst in ein
öffentliches Repository auf GitHub zu veröffentlichen. Der C2
unter lhr.life ist Backup. Der primäre Kanal ist git push. Für
einen Verteidiger, der den Egress beobachtet, ist das nicht von der
normalen CI des Entwicklers zu unterscheiden. Für GitHub ist es —
bis jemand das Repo meldet — ein legitimes öffentliches Projekt
eines echten Nutzers. Die Exfiltration wird durch die Identität
des Opfers gewaschen.
Was der Agent macht, während Sie weiter scrollen.
Wenn Sie einen Coding-Agenten in Ihrem Terminal haben — Claude Code,
Cursor's CLI, Codex CLI, Aider, suchen Sie sich einen aus — besteht
eine ungleich null Wahrscheinlichkeit, dass der Agent in der Zeit,
die Sie zum Lesen des letzten Absatzes gebraucht haben, in Ihrem
Auftrag ein npm install ausgeführt hat. Vielleicht zwei.
Coding-Agenten halten nicht inne, um Abhängigkeitsbäume zu bewundern.
Der ganze Grund, warum Sie sich einen gekauft haben, ist, dass er
nicht innehält.
Die Pakete, die OX erwischt hat, sind Typosquats, und das ist eine
Fehlerkategorie, die ganz besonders zur Maschinengeschwindigkeit
passt. Ein Mensch, der chalk-template tippen muss, wird die
Buchstaben in der richtigen Reihenfolge hinbekommen, weil er das
hundert Mal gemacht hat. Ein Modell, das jeden Stack-Overflow-Post
der Welt aufgenommen hat, hat chalk-template und chalk-tempalte
im selben Trainingskorpus gesehen — letzteres typischerweise in
einem Screenshot des Fehlers von jemand anderem — und wird auf
einen Prompt wie „füge meiner CLI farbige Ausgabe hinzu" hin manchmal
den Tippfehler wortwörtlich ausspucken. Der Agent zuckt nicht
zusammen. Der Paketmanager zuckt nicht zusammen. Das
prepare-Skript läuft.
Das ist kein hypothetischer Fehlermodus. Es ist der Fehlermodus, für den die Shai-Hulud-Familie entworfen wurde. Der ursprüngliche Wurm verbreitete sich, indem er Maintainer-Tokens stahl und damit weitere kompromittierte Versionen legitim populärer Pakete neu veröffentlichte. Die Nachahmer haben die Maintainer-Tokens noch nicht; was sie haben, ist der Typosquat-Namensraum, in den Agenten besonders gut hineinfallen.
Wo Bromure in dieser Geschichte sitzt.
Bromure Agentic Coding ist die Konfiguration,
in der der Coding-Agent innerhalb einer aufgabenspezifischen,
wegwerfbaren Linux-VM läuft, mit eingehängtem Projektordner,
vermitteltem Egress und Anmeldedaten, die auf der macOS-Host-Seite
des Hypervisors gehalten werden. Wir sind die Architektur im Detail
im Bitwarden-CLI-Artikel
und im @tanstack-Artikel
durchgegangen. Was nun folgt, ist, was genau mit jedem dieser vier
Pakete innerhalb dieser Grenze passiert.
Gehen wir das gegen die vier Pakete einzeln durch, denn in den Details verdient die Architektur ihr Geld.
chalk-tempalte greift nach $GH_TOKEN.
Der Signaturzug des Shai-Hulud-Klons besteht darin, das
GitHub-Token des Entwicklers zu nehmen und damit ein öffentliches
Repository auf dem eigenen Konto des Entwicklers zu erstellen.
Innerhalb einer Bromure-VM ist das $GH_TOKEN, das er liest, ein
Stub — ein syntaktisch gültiger String, der mit ghp_ beginnt und
genau aus diesem Grund existiert. Die erste Aktion des Runners ist
ein POST /user/repos gegen api.github.com. Der Egress-Proxy
auf der Host-Seite erkennt api.github.com als whitelisted
Endpunkt — aber nur für die Operationen, die die aktuelle Aufgabe
tatsächlich angefordert hat: git push auf das Repo, an dem die
Aufgabe arbeitet, gh pr create gegen dasselbe Repo,
gh api repos/das/repo/issues. „Ein frisches öffentliches
Repository auf dem Konto des Nutzers erstellen" steht nicht auf
dieser Liste, weil der Nutzer nicht danach gefragt hat. Der Proxy
weigert sich, das echte Token zu substituieren, und der Stub geht
als Stub raus. GitHub gibt 401 zurück. Der Exfiltrationskanal des
Wurms — der clevere Kanal, der darauf ausgelegt ist,
DNS-Egress-Filterung zu umgehen — öffnet sich nie.
Der Backup-Kanal, der lhr.life-Tunnel unter
87e0bbc636999b.lhr.life, ist ebenfalls nicht whitelisted. Der
Trace protokolliert den Versuch. Die Bytes verlassen nichts.
axois-utils installiert Phantom Bot zur Persistenz.
Der Golang-Bot versucht, sich in den Windows-Autostart-Ordner zu
schreiben und eine geplante Aufgabe zu erstellen. Die Bromure-VM
ist ein Linux-Guest, also ist die Windows-spezifische Persistenz
kostenlos ein No-op. Bei einer Linux-Variante derselben Payload —
die jemand bald ausliefern wird — würde sich der Bot in
/etc/cron.d/ oder ~/.config/systemd/user/ schreiben. Beide
Pfade liegen innerhalb der wegwerfbaren Copy-on-Write-Platte des
Guests. Der nächste bromure reset, oder das natürliche Ende der
aktuellen Aufgabe, lässt die Platte fallen. Die Persistenz ist weg
ohne jegliche Jagd.
In der Zwischenzeit steht die ausgehende Verbindung des Bots zu
b94b6bcfa27554.lhr.life nicht auf der Egress-Whitelist der
Aufgabe, weil keine legitime Coding-Aufgabe mit einem frisch
registrierten lhr.life-Tunnel spricht. Der Bot telefoniert nach
Hause in einen geschlossenen Socket. Der Session-Trace protokolliert
den Versuch — nützlich morgen früh, wenn eine IOC-Liste
veröffentlicht wird.
@deadcode09284814/axios-util POSTet rohe Anmeldedaten.
Die einfachste der vier Payloads ist auch die, die am wenigsten zu
greifen hat. Der Runner liest ~/.ssh, ~/.aws, Env-Vars des
Guests und POSTet sie an 80.200.28.28:2222. Das SSH-Verzeichnis
ist leer. Die AWS-Datei ist ein Stub. Die Umgebungsvariablen sind
entweder Stubs oder nicht gesetzt. Die Ziel-IP ist nicht whitelisted.
Entweder wird die Verbindung am Proxy blockiert, oder sie verlässt
den Host mit einer Payload aus Platzhaltern. Beide Ergebnisse sind in
Ordnung.
color-style-utils sucht nach Wallets, die nicht da sind.
Der Krypto-Dieb ist das Paket, dessen Bedrohungsmodell am klarsten
davon ausgeht, dass der Browser des Entwicklers auf derselben
Maschine läuft. Er liest Pfade wie
~/Library/Application Support/Google/Chrome/Default/Local Extension Settings/<MetaMask-id>/
und die Äquivalente für Phantom und Keplr. Keiner dieser Pfade
existiert auf der Bromure-VM. Die VM hat Ihr Chrome-Profil nicht
in sich. Die VM hat keine Wallet-Erweiterung installiert. Die VM
ist per Design niemandes Haupt-Browser. Der Runner findet ein
leeres Verzeichnis und macht weiter.
Das ist der Teil, der keine Geschichte über Anmeldedaten ist, die auf dem Host leben. Die Wallets leben auf dem Host, weil auf einem normalen Laptop der Browser des Entwicklers und der Coding-Agent des Entwicklers ein Dateisystem teilen. Bromure macht die Wallet nicht stärker; es macht sie unerreichbar von dem Ort, an dem der Wurm läuft. Der Wurm kann nicht lesen, was nicht auf seiner Platte ist.
Was trotzdem wehtut.
Es gibt Ecken dieser Geschichte, in denen Bromures Aufgaben-VM keine Lösung ist, und sie verdienen es, laut benannt zu werden.
Der Projektordner ist eingehängt.
Dateien, die der Wurm in den Projektordner schreibt —
einschließlich der Persistenz im Stil
.claude/router_runtime.js, die wir im @tanstack-Beitrag
behandelt haben — überdauern Task-Resets, weil genau das der Sinn
des Einhängens des Projektordners ist. Die Verteidigung dort
ist nicht die VM. Es ist git status und ein fünfsekündiger
Blick auf das Diff, bevor Sie pushen. Der Trace macht es
einfacher zu erkennen, welche Sessions unerwartete Dateien
hinzugefügt haben.
Die Egress-Whitelist ist absichtlich schmal.
Bromures Credential-Broker funktioniert, weil die Whitelist
schmal ist. Wenn Sie npm publish für Ihren eigenen Scope
freischalten, weil Sie heute ein Release veröffentlichen, und
Sie zufällig heute eines dieser vier Pakete installieren, wird
der Wurm unter Ihrem Scope veröffentlichen. Schalten Sie frei,
was die Aufgabe braucht. Keinen Byte mehr.
Ein Token für diese Aufgabe ist immer noch ein echtes Token.
Das Stub-GitHub-Token wird am Draht gegen ein echtes ausgetauscht
— für Operationen, die die Aufgabe whitelisted hat. Wenn
chalk-tempalte den Agenten dazu bringen könnte, einen
git push zum eigenen Repo des Projekts zu machen, würde
dieser Push mit einem echten Token durchgehen. Die Grenze
schützt die Anmeldedaten. Sie prüft das Diff nicht. Lesen Sie
das Diff.
Erkennung ist dem Trace nachgelagert.
Der Session-Trace zeichnet jeden Shell-Befehl, jeden
Dateischreibvorgang und jede ausgehende Anfrage auf. Er
klassifiziert von sich aus nicht 87e0bbc636999b.lhr.life als
bösartig. Er zeichnet auf, dass die Anfrage gestellt wurde. Wenn
OX morgen früh eine frische IOC-Liste veröffentlicht, dauert
Ihre Suche zwei Sekunden. Das ist der Wert, den der Trace
hinzufügt — keine Magie, nur Belege.
Eine letzte Sache.
Der Leak ist nicht die Nachricht. Die Nachricht ist, was der Leak
über das nächste Jahr hinweg wahrscheinlich macht: eine Menge
kleiner, halbkompetenter Forks eines Wurms, den das npm-Ökosystem
selbst in seiner kompetenten Form gerade noch rechtzeitig erwischt
hat. Manche der Forks werden laut genug sein, um einen Bericht zu
bekommen. Die meisten werden eine Woche im Registry sitzen, ein
paar tausend npm installs einsammeln und verschwinden, wenn
endlich jemand einen Missbrauchsbericht einreicht. Die
zweitausendsechshundertachtundsiebzig Installationen, die OX bei
den deadcode09284814-Paketen gezählt hat, sind kein Ausreißer.
Sie sind der Durchschnitt.
Die ehrliche Frage lautet nicht „wird mein Team jeden vergifteten Typosquat in npm meiden". Die Agenten tippen schnell. Die Namen sind billig. Die ehrliche Frage lautet: Wenn der Agent eines davon installiert — und über das nächste Jahr hinweg, in einem Team, das Agenten nutzt, wird er das — findet das Post-Install-Skript die Hände des Entwicklers, oder findet es eine wegwerfbare Linux-Box mit Stubs in den Anmeldedaten-Dateien und einem Proxy, der nicht weiß, wer er ist.
Bromure Agentic Coding ist das zweite. Es ist kostenlos, Open Source und heute schon ausgeliefert. Der Fork-Baum wird schlimmer werden, bevor er besser wird.