Skip to main content

Mini Shai-Hulud trifft AntV: Über 300 schädliche npm-Pakete über kompromittiertes Maintainer-Konto veröffentlicht

Artikel von
blog feature supply chain sbom

18. Mai 2026

0 Min. Lesezeit

Ein Supply-Chain-Angriff auf das Datenvisualisierungs-Ökosystem @antv und zugehörige npm-Pakete breitet sich aktiv über die npm-Registry aus. Der Angriff, der einer Bedrohungsgruppe namens TeamPCP zugeschrieben und als weitere Welle der Mini-Shai-Hulud-Kampagne bezeichnet wird, veröffentlichte am 19. Mai 2026 in einer automatisierten Welle innerhalb von 22 Minuten mehr als 300 schädliche Paketversionen in 323 Paketen. Zusammen kommen die Pakete auf etwa 16 Millionen Downloads pro Woche.

Der Angriffsvektor war ein kompromittiertes npm-Maintainer-Konto. Die in den betroffenen Paketen eingebettete Malware stiehlt Entwicklerinformationen und Cloud-Zugangsdaten, richtet dauerhaften C2-Zugriff ein und versucht, sich mithilfe gestohlener npm-Token auf weitere Pakete auszubreiten.

Kurzfassung

Angriffstyp

Supply-Chain-Angriff, kompromittiertes Maintainer-Konto

Bedrohungsakteur

TeamPCP (Aliasse: DeadCatx3, PCPcat)

Kampagne

Mini Shai-Hulud (läuft seit Sep. 2025)

Datum des Vorfalls

19. Mai 2026, 01:39–02:06 UTC

Kompromittierte Pakete

637 schädliche Versionen in 323 Paketen

Geschätzte Downloads pro Woche

~16 Millionen

Verhalten der Malware

Diebstahl von Zugangsdaten, Abgreifen von Cloud-Geheimnissen, Persistenz, Wurmausbreitung

Snyk-Abdeckung

Security-Advisories in der Snyk Vulnerability Database; Zero Day Report in der App verfügbar

Sofortmaßnahmen

Auf Versionen vor dem 19. Mai festlegen, npm install --ignore-scripts ausführen, alle Zugangsdaten erneuern

Betroffene Pakete

Das kompromittierte npm-Konto atool verwaltete 547 Pakete. Die schädlichen Veröffentlichungen betrafen in zwei Wellen mehr als 300 davon:

  • Erste Welle: 01:39–01:56 UTC (~317 Versionen)

  • Zweite Welle: 02:05–02:06 UTC (~314 Versionen)

Zu den betroffenen Paketen mit den meisten Downloads gehören:

Paket

Snyk Advisor

Monatliche Downloads

size-sensor

4,2 Mio.

echarts-for-react

3,8 Mio.

@antv/scale

2,2 Mio.

timeago.js

1,15 Mio.

@antv/g6

Über 1,0 Mio.

Zu den kompromittierten Kernpaketen von @antv gehören @antv/g2, @antv/g6, @antv/x6, @antv/l7, @antv/s2, @antv/f2, @antv/g, @antv/g2plot, @antv/graphin und @antv/data-set. Betroffen sind außerdem nicht gescopte Pakete wie echarts-for-react, timeago.js, size-sensor und canvas-nest.js.

AntV ist eine aus Alibaba hervorgegangene Suite für Datenvisualisierung, die häufig in Unternehmens-Dashboards, Finanzberichten und Graphanalyse-Plattformen eingesetzt wird. Aufgrund der weiten Verbreitung ist das Paketportfolio des Maintainer-Kontos ein besonders attraktives Ziel.

So funktioniert der Angriff

Phase 1: Kompromittierung des Maintainer-Kontos

Der Angriff beginnt mit der Kompromittierung des npm-Kontos atool. Wie das Konto übernommen wurde, wird noch untersucht. Durch die Kontrolle über das Konto erhielt der Angreifer Veröffentlichungszugriff auf alle 547 Pakete, die es verwaltet.

Phase 2: Automatisierte Veröffentlichung schädlicher Pakete

Der Angreifer veröffentlichte in zwei rasch aufeinanderfolgenden Wellen schädliche Versionen und aktualisierte die meisten Pakete zweimal (einige wenige Pakete, die früh getestet wurden, erhielten drei Versionen). Jedes schädliche Paket-Tarball enthält zwei Ergänzungen:

  • Eine Datei index.js: im Stammverzeichnis: ein stark verschleierter Bun-JavaScript-Payload mit 498 KB

  • Eine Änderung an package.json mit folgendem Eintrag: "preinstall": "bun run index.js"

Der Lifecycle-Hook preinstall wird automatisch ausgelöst, wenn ein Entwickler npm install ausführt – noch bevor andere Installationsschritte beginnen.

Phase 3: Einschleusen eines verwaisten Commits für Sigstore-Provenance

Eine der subtileren Techniken dieser Welle ist das Einschleusen einer optionalen Abhängigkeit, die auf einen verwaisten Commit im legitimen Repository antvis/G2 verweist:

"optionalDependencies": {
  "@antv/setup": "github:antvis/G2#1916faa365f2788b6e193514872d51a242876569"
}

Wichtig ist, dass es sich bei der GitHub-Abhängigkeit um dieselbe Angriffsmethode handelt, die bereits beim vorherigen TanStack-Shai-Hulud-Supply-Chain-Angriff zum Einsatz kam.

Der Commit wurde vom Angreifer erstellt, aber so gefälscht, dass er den Anschein erweckte, von huiyu.zjt <huiyu.zjt@ant.com> (einem tatsächlichen Maintainer) zu stammen. Schreibzugriff auf das Ziel-Repository war nicht erforderlich. Der Angreifer forkte antvis/G2, erstellte einen verwaisten Commit mit dem Payload und löschte anschließend den Fork. GitHub speichert Objekte aus gelöschten Forks, bis die Garbage Collection ausgeführt wird. Dadurch bleibt der schädliche Commit über seinen Hash zugänglich.

Das Abrufen dieses Commits ermöglicht es, den Payload mit Git-Zugangsdaten auszuführen, während es so aussieht, als würde auf ein vertrauenswürdiges Repository verwiesen.

Mithilfe gestohlener GitHub-Actions-OIDC-Token kann die Malware anschließend bei Fulcio (https://fulcio.sigstore.dev) Signaturzertifikate anfordern und über Rekor (https://rekor.sigstore.dev) in-toto-Provenance-Erklärungen erstellen. So entstehen Pakete mit kryptografisch gültigen SLSA-Build-Level-3-Attestierungen.

Die zentrale Erkenntnis: Die Signaturen sind legitim, weil die Build-Pipeline selbst kompromittiert wurde. Sigstore-Provenance gibt an, welche Pipeline ein Artefakt erstellt hat – nicht, ob diese Pipeline wie vorgesehen funktioniert hat. Ein verbreiteter Irrtum ist daher, Attestierungsnachweise für veröffentlichte Pakete allein als absolut zuverlässiges Legitimitätssignal zu betrachten.

Phase 4: Abgreifen von Zugangsdaten

Wird bun run index.js auf dem Rechner eines Entwicklers oder in einem CI-Runner ausgeführt, zielt der Payload auf mehr als 80 Umgebungsvariablen und über 100 Dateipfade. Zu den anvisierten Zugangsdaten gehören:

  • AWS: Zugriffsschlüssel (AKIA[0-9A-Z]{16}), Session-Token, EC2 IMDS (169.254.169.254), ECS-Metadaten (169.254.170.2), Secrets Manager

  • GCP: JSON-Dateien für Dienstkonten, Standardanmeldedaten für Anwendungen

  • Azure: Anmeldedaten für Dienstprinzipale

  • GitHub: PATs und OIDC-Token (gh[op]_[A-Za-z0-9]{36,})

  • npm: Veröffentlichungstoken mit dem Berechtigungsumfang bypass_2fa

  • Infrastruktur: Kubernetes-Diensttoken, HashiCorp-Vault-Token

  • Datenbanken: Verbindungszeichenfolgen für MongoDB, MySQL, PostgreSQL und Redis

  • Dienste: Stripe-Schlüssel, Slack-Token, Docker-Authentifizierungskonfigurationen

  • SSH-Schlüssel: ~/.ssh/id_*

In GitHub-Actions-Umgebungen versucht der Payload, Geheimnisse direkt aus dem Speicher des Runner.Worker-Prozesses über /proc/{pid}/mem auszulesen und so die Maskierung von Geheimnissen vollständig zu umgehen.

Phase 5: Datenexfiltration

Alle abgegriffenen Zugangsdaten werden als JSON serialisiert, mit gzip komprimiert und mit AES-256-GCM verschlüsselt. Anschließend wird der Verschlüsselungsschlüssel mithilfe von RSA-OAEP und einem fest codierten öffentlichen Schlüssel des Angreifers verpackt. Dadurch können Verteidiger, die die exfiltrierten Daten finden, nicht feststellen, welche Daten gestohlen wurden.

Die Exfiltration erfolgt über zwei Kanäle:

  1. Primärer C2-Kanal: https://t[.]m-kosche[.]com:443/api/public/otel/v1/traces (getarnt als OpenTelemetry-Trace-Daten)

  2. Sekundärer GitHub-Dead-Drop: Wird ein GitHub-Token gefunden, erstellt der Payload im Konto des Opfers Repositories mit Namen, die sich auf Dune beziehen (Kombinationen aus Wörtern wie sardaukar, fremen, atreides und sandworm, ornithopter, stillsuit sowie einer Zahl von 0 bis 999). Die README-Dateien enthalten typische, rückwärts geschriebene Formulierungen aus früheren Wellen der Shai-Hulud-Kampagne (z. B. „niagA oG eW ereH :duluH-iahS“). Gestohlene Daten werden als results/results-<timestamp>-<counter>.json committet. HTTP-Anfragen verwenden "python-requests/2.31.0" als User-Agent.

Phase 6: Persistenz

Der Payload installiert mehrere Persistenzmechanismen, die eine einfache Deinstallation mit npm uninstall überstehen:

  • Übernahme von KI-Coding-Agenten: Erstellt .claude/settings.json mit einem SessionStart-Hook, der node .claude/setup.mjs ausführt. Dadurch wird die Malware erneut ausgeführt, sobald ein Entwickler in einem betroffenen Verzeichnis eine neue Claude-Code-Sitzung öffnet. Wir weisen darauf hin, dass ein ähnliches Muster auch in früheren Supply-Chain-Angriffskampagnen wie TanStack zu beobachten war.

  • IDE-Hooks: Ändert .vscode/tasks.json mit "runOn": "folderOpen", damit der Code beim Öffnen des Projekts ausgeführt wird.

  • Daemon auf Betriebssystemebene: Installiert ~/.local/share/kitty/cat.py, einen Hintergrund-Daemon, der stündlich die GitHub-Commit-Such-API nach Befehlen mit dem Schlüsselwort firedalazer abfragt. Die Befehle werden mit RSA-PSS und einem fest codierten 4096-Bit-öffentlichen Schlüssel signiert. So kann der Angreifer beliebigen Python-Code zur Ausführung auf kompromittierten Rechnern einschleusen – auch lange nach der ersten Infektion. Unter Linux wird der Daemon als systemd-Benutzerdienst registriert (~/.config/systemd/user/kitty-monitor.service), unter macOS als LaunchAgent (~/Library/LaunchAgents/com.user.kitty-monitor.plist).

Token-Überwachung: ~/.local/bin/gh-token-monitor.sh fragt gestohlene GitHub-Token in Abständen von 60 Sekunden ab. So kann der Angreifer schnell reagieren, wenn ein Token kurz vor dem Ablauf steht.

Phase 7: Wurmausbreitung

Der Payload sucht nach npm-Token mit dem Berechtigungsumfang bypass_2fa und verwendet sie, um weitere Pakete erneut zu veröffentlichen, auf die das kompromittierte Konto Zugriff hat. In GitHub-Actions-Umgebungen tauscht er das Actions-OIDC-Token gegen npm-Veröffentlichungstoken für einzelne Pakete ein über:

POST https://registry.npmjs.org/-/npm/v1/oidc/token/exchange/package/<package-name>

Außerdem fügt er einen GitHub-Actions-Workflow auf einem Branch namens chore/add-codeql-static-analysis ein. Die Workflow-Datei heißt "Run Copilot" (.github/workflows/codeql.yml). Der Workflow schreibt toJSON(secrets) in ein Artefakt namens format-results.txt und entfernt sich anschließend selbst, indem er den Workflow-Lauf löscht.

Auswirkungsanalyse

Unmittelbar betroffen sind alle Entwicklungs- oder CI-Umgebungen, in denen zwischen 01:39 und etwa 02:18 UTC am 19. Mai 2026 npm install mit einer betroffenen Paketversion ausgeführt wurde.

CI/CD-Umgebungen sind besonders gefährdet. Dort kann der Payload alle Geheimnisse aus dem Runner-Prozess auslesen, nicht nur die, die ausdrücklich als Umgebungsvariablen übergeben wurden. Alle Geheimnisse, auf die der GitHub-Actions-Runner Zugriff hat – darunter OIDC-Token, Repository-Geheimnisse und auf dieses Repository beschränkte Organisationsgeheimnisse –, sollten als kompromittiert gelten, wenn eine betroffene Version installiert wurde.

Auch Entwicklerrechner sind erheblich gefährdet. Wegen der Persistenzmechanismen reicht es nicht aus, nur die betroffenen Pakete zu entfernen. Der Hook in .claude/settings.json, die VS-Code-Aufgabe und der System-Daemon laufen weiter, bis sie ausdrücklich entfernt werden.

Durch die Selbstverbreitung könnte jedes npm-Token, das von einem Entwicklerrechner oder CI-Runner abgegriffen wurde, dazu verwendet werden, weitere Pakete außerhalb des ursprünglichen Paketportfolios des atool-Kontos zu vergiften. Dadurch weitet sich der Schadensradius über AntV und verwandte Pakete hinaus aus.

Erkennung

Prüfen Sie Ihre Lockdatei. Wenn in Ihrer package-lock.json oder yarn.lock ein Paket aufgeführt ist, das vom Konto atool verwaltet wird, prüfen Sie, ob die aufgelöste Version zwischen 01:39 und 02:18 UTC am 19. Mai 2026 veröffentlicht wurde.

Scannen Sie Ihre Projekte mit Snyk. Snyk hat in der Snyk Vulnerability Database Advisories zu betroffenen Paketversionen veröffentlicht und eine In-App-Benachrichtigung sowie einen Zero Day Report bereitgestellt, mit denen Kunden die Betroffenheit in ihren Organisationen untersuchen können.

snyk test

Für einen schnellen Scan eines bestimmten Pakets in Ihrem Abhängigkeitsbaum:

snyk test --file=package-lock.json

Suchen Sie nach Persistenzartefakten. Wenn Sie betroffene Pakete installiert haben, prüfen Sie Folgendes:

# AI agent hook
cat .claude/settings.json 2>/dev/null | grep -A5 SessionStart

# VS Code task hook
cat .vscode/tasks.json 2>/dev/null | grep "folderOpen"

# C2 daemon
ls ~/.local/share/kitty/cat.py 2>/dev/null
ls ~/.local/bin/gh-token-monitor.sh 2>/dev/null
systemctl --user status kitty-monitor 2>/dev/null  # Linux
launchctl list com.user.kitty-monitor 2>/dev/null   # macOS

# Dead-drop repositories on your GitHub account
gh repo list --json name,description | grep -E "sardaukar|mentat|fremen|atreides|harkonnen|gesserit|fedaykin|tleilaxu"

Indikatoren auf Paketebene:

  • Vorhandensein des preinstall-Skripts bun run index.js in node_modules/<package>/package.json

  • SHA256 des Payloads: a68dd1e6a6e35ec3771e1f94fe796f55dfe65a2b94560516ff4ac189390dfa1c

  • Optionale Dependency mit Verweis auf github:antvis/G2#1916faa365f2788b6e193514872d51a242876569 (oder Commits 7cb42f57561c / dc3d62a2181b)

Netzwerkindikatoren:

  • Ausgehende Anfragen an 169.254.169.254 oder 169.254.170.2 (Cloud-Metadaten-Endpunkte) aus Umgebungen außerhalb der Cloud

  • HTTP-Anfragen an t.m-kosche.com:443 mit OpenTelemetry-Pfaden

  • GitHub-API-Aufrufe mit dem User-Agent python-requests/2.31.0, die nicht von tatsächlichen Python-Prozessen stammen

Behebung

Wenn Sie nicht sicher sind, ob Sie betroffen waren, gehen Sie von einer bestätigten Kompromittierung aus. Aufgrund der RSA-verschlüsselten Exfiltration können Sie die gestohlenen Daten nicht wiederherstellen.

Schritt 1: Entfernen Sie Persistenzmechanismen, bevor Sie Tokens widerrufen.

Der Daemon gh-token-monitor.sh fragt Tokens alle 60 Sekunden ab. Läuft der Daemon noch, wenn ein GitHub-Token abläuft oder widerrufen wird, kann dies weitere schädliche Aktionen auslösen. Stoppen und entfernen Sie zuerst die Persistenzmechanismen:

# Remove systemd service (Linux)
systemctl --user stop kitty-monitor
systemctl --user disable kitty-monitor
rm -f ~/.config/systemd/user/kitty-monitor.service

# Remove LaunchAgent (macOS)
launchctl unload ~/Library/LaunchAgents/com.user.kitty-monitor.plist
rm -f ~/Library/LaunchAgents/com.user.kitty-monitor.plist

# Remove C2 daemon and monitor
rm -f ~/.local/share/kitty/cat.py
rm -f ~/.local/bin/gh-token-monitor.sh

# Remove editor hooks
rm -f .claude/settings.json  # or edit to remove SessionStart hook
# Edit .vscode/tasks.json to remove any "runOn": "folderOpen" tasks

# Check for injected GitHub workflows
git log --oneline --all | grep -i codeql

Schritt 2: Bereinigen Sie npm und installieren Sie saubere Versionen neu.

# Remove node_modules
rm -rf node_modules

# Downgrade affected packages to pre-May 19 versions in package.json, then:
npm install --ignore-scripts

Mit --ignore-scripts wird verhindert, dass während der Installation Lifecycle-Skripte wie preinstall, postinstall oder prepare ausgeführt werden. Dies sollte unabhängig davon in CI-Umgebungen Standard sein.

Schritt 3: Rotieren Sie alle Zugangsdaten.

Gehen Sie davon aus, dass alles kompromittiert ist, worauf von einem Rechner oder CI-Runner aus zugegriffen werden kann, auf dem ein betroffenes Paket installiert wurde:

  • npm-Publish-Tokens

  • Persönliche GitHub-Access-Tokens und Actions-Secrets

  • AWS-Access-Keys (und alle IAM-Rollen, auf die betroffene Runner zugreifen können)

  • GCP-Service-Account-Keys

  • Azure-Service-Principals

  • Kubernetes-Service-Account-Tokens

  • HashiCorp-Vault-Tokens

  • SSH-Schlüssel auf betroffenen Rechnern

  • Datenbank-Verbindungszeichenfolgen

  • Alle API-Keys oder Service-Tokens, die in Umgebungsvariablen oder Konfigurationsdateien gespeichert sind

Schritt 4: Prüfen Sie GitHub auf eingeschleuste Workflows und Dead-Drop-Repositories.

# Check for attacker-injected branches
git branch --all | grep "codeql-static-analysis"

# Check for Dune-named repositories created on your account
gh repo list --json name | grep -E "sardaukar|mentat|fremen|atreides|harkonnen"

# Check npm audit log for unexpected publishes
npm access ls-packages

Schritt 5: Beugen Sie künftigen Vorfällen vor.

  • Aktivieren Sie die Zwei-Faktor-Authentifizierung für npm mit Publish-Schutz für alle Pakete Ihrer Organisation.

  • Fügen Sie npm install --ignore-scripts standardmäßig zur CI-Konfiguration hinzu.

  • Fixieren Sie Dependencies auf exakte Versionen und verwenden Sie Lockfiles mit Integritätsprüfungen.

  • Erwägen Sie eine Abkühlungsrichtlinie für die Registry: Markieren Sie Pakete, die in den letzten 7 Tagen veröffentlicht wurden, und halten Sie sie zurück.

  • Verwenden Sie Snyk, um Ihren Dependency-Baum kontinuierlich auf schädliche Pakete zu überwachen, sobald diese gemeldet werden.

  • Wir empfehlen Ihnen dringend, das Repository mit npm-Sicherheits-Best-Practices zu konsultieren und dessen Empfehlungen zu befolgen, um künftige Malware-Vorfälle durch geeignete Sicherheitsmaßnahmen und Vorgehensweisen zu vermeiden.

Die größere Kampagne: Shai-Hulud-Wellen

Der AntV-Angriff ist die jüngste Welle einer Kampagne, die TeamPCP seit September 2025 betreibt. Die Entwicklung zeigt eine stetige Eskalation hinsichtlich Umfang, Persistenz, Raffinesse und Missbrauch vertrauenswürdiger Infrastruktur:

Welle

Datum

Hauptziel

Umfang

Charakteristische Technik

Welle 1 (Shai-Hulud)

Sep. 2025

npm (breit gestreut)

~4 Pakete

Erster sich selbst verbreitender npm-Wurm

Welle 2 (SHA1-Hulud)

Nov. 2025

Zapier, Posthog, Postman

600+ Pakete

Container-Ausbrüche; destruktiver Wiper

Welle 3 (Mini, SAP)

Apr. 2026

SAP CAP-JS, MBT

4 Pakete

Einschleusung eines Claude Code-SessionStart-Hooks

Welle 4 (TanStack)

11. Mai 2026

@tanstack/*

84 Versionen/42 Pakete

Erster gültiger SLSA-Provenienz-Nachweis durch OIDC-Hijacking

Welle 5 (AntV)

19. Mai 2026

@antv/* + 310 weitere

637 Versionen/323 Pakete

Kompromittiertes Maintainer-Konto; erweiterte C2-Infrastruktur

Snyk hat frühere Wellen ausführlich behandelt:

Jede Welle hat die auf der Bun-Runtime basierende, verschleierte Payload wiederverwendet und erweitert. Hinzu kamen neue Persistenzmechanismen (der Claude Code-SessionStart-Hook tauchte erstmals in Welle 3 auf), neue Exfiltrationsinfrastruktur und neue Methoden zum Fälschen vertrauenswürdiger Provenienz. Besonders das Problem mit der SLSA-Provenienz verdient Aufmerksamkeit: Eine gültige Sigstore-Attestierung bestätigt, welche Pipeline ein Paket erstellt hat – nicht, ob diese Pipeline kompromittiert wurde. Wer sich auf Provenienz als Vertrauenssignal verlässt, ohne zugleich die zugrunde liegende Pipeline-Konfiguration zu prüfen, lässt eine Lücke, die diese Kampagne nun in zwei aufeinanderfolgenden Wellen ausgenutzt hat.

Ein Video zur Behebung der umfassenderen Shai-Hulud-Kampagne mit Snyk:

Shai-Hulud NPM Attack: Remediation with Snyk

Shai-Hulud-NPM-Angriff: Behebung mit Snyk — Anleitung zum Erkennen und Beheben kompromittierter Pakete mit Snyk-Tools.

Zeitlicher Ablauf des Angriffs (19. Mai 2026, UTC)

Uhrzeit

Ereignis

01:39

Erste schädliche Paketversion wird vom Konto atool veröffentlicht

01:56

Erste Veröffentlichungswelle endet (~317 Versionen)

02:05

Zweite Welle beginnt

02:06

Zweite Welle endet (~314 weitere Versionen)

~02:18

Angriff wird entdeckt; Sicherheitsforscher beginnen, Meldungen einzureichen

Laufend

Die Untersuchung läuft weiter; möglicherweise werden weitere Pakete identifiziert

Snyk-Abdeckung

Snyk hat Hinweise zu betroffenen Paketversionen in der Snyk Vulnerability Database veröffentlicht. Snyk-Kunden können im Produkt den Zero Day Report verwenden, um zu untersuchen, welche Projekte in ihrer Organisation betroffen sind. Die Einträge zu betroffenen Paketen in der Snyk Vulnerability Database geben den aktuellen Status wieder.

Hintergrund zu dieser Angriffskategorie bietet die Lektion von Snyk Learn zu Kompromittierung legitimer Pakete. Sie erklärt, wie die Kompromittierung von Maintainer-Konten in die umfassendere Bedrohungslandschaft der Supply Chain einzuordnen ist.

Sichern Sie Ihre Supply Chain mit Snyk

87 % der Befragten waren von Problemen mit der Supply-Chain-Sicherheit betroffen. Schützen Sie Ihre Supply Chain mit Snyk.