Skip to main content

„Ein Mini Shai-Hulud ist aufgetaucht“: Bun-basierter Stealer trifft SAP-@cap-js- und mbt-npm-Pakete

Artikel von

29. April 2026

0 Min. Lesezeit

Am 29. April 2026 veröffentlichten Angreifer manipulierte Versionen von vier npm-Paketen aus dem SAP-Entwicklungsökosystem: mbt, @cap-js/db-service, @cap-js/sqlite und @cap-js/postgres. Jede kompromittierte Version enthält einen preinstall-Hook, der die Bun-JavaScript-Laufzeitumgebung von GitHub Releases herunterlädt und damit einen etwa 11,6 MB großen, verschleierten Credential-Stealer ausführt.

Die Payload versieht sich mit der fest codierten Beschreibung „A Mini Shai-Hulud has Appeared“. Diese taucht in Echtzeit in öffentlichen GitHub-Suchergebnissen auf, während kompromittierte Entwicklerrechner in den eigenen Konten ihrer Opfer Dead-Drop-Repositories anlegen. Die Kampagne greift den Namen Shai-Hulud erneut auf (die Dead-Drop-Repositories sind entsprechend gekennzeichnet) und enthält laut der vollständigen Entschlüsselung von StepSecurity funktionsfähigen npm-Selbstausbreitungscode. Zum Zeitpunkt der Veröffentlichung wurden in freier Wildbahn nur die vier ursprünglich kompromittierten Pakete beobachtet. Die technische Analyse und Details zum kompromittierten npm-Konto, über das die ersten Veröffentlichungen ermöglicht wurden, finden Sie weiter unten.

Snyk hat für alle vier kompromittierten Versionen Advisories veröffentlicht. Die betroffenen Releases werden von snyk test erkannt und sind auf der Seite der jeweiligen Pakete in der Snyk Security Database aufgeführt.

Betroffene Pakete und Snyk-Advisories

Paket

Kompromittierte Version

Snyk-Advisory

Ungefähre wöchentliche Downloads

mbt

1.2.48

~52.000

@cap-js/db-service

2.10.1

~260.000

@cap-js/sqlite

2.2.2

~250.000

@cap-js/postgres

2.2.2

~10.000

Wöchentliche Downloadzahlen aus der öffentlichen Downloads-API der npm-Registry für die Woche vor der Kompromittierung (22.–28. April 2026). Alle vier Pakete gehören zur Toolchain des SAP Cloud Application Programming Model. mbt ist das über npm vertriebene Cloud MTA Build Tool, mit dem Bereitstellungsarchive für SAP-Cloud-Anwendungen erstellt werden. Die Pakete @cap-js/* stellen Datenbankdienste für CAP-Anwendungen bereit.

Die schädlichen Versionen wurden am 29. April 2026 innerhalb eines kurzen Zeitfensters veröffentlicht (alle Zeitangaben in UTC). Die Zeitstempel wurden direkt anhand von registry.npmjs.org und der GitHub API überprüft:

  • 09:55:25: mbt@1.2.48 wird über das npm-Konto cloudmtabot veröffentlicht.

  • 10:01:07: Das erste Dead-Drop-Repository eines Opfers erscheint auf GitHub (gruposbftechrecruiter/siridar-navigator-935, laut GitHub-API-Zeitstempeln).

  • 11:25:47: @cap-js/sqlite@2.2.2 wird veröffentlicht.

  • 12:03 to 12:04: StepSecurity reicht Offenlegungsmeldungen zu cap-js/cds-dbs#1588 und SAP/cloud-mta-build-tool#1224 ein. Eine dritte unabhängige Offenlegungsmeldung, SAP/open-ux-tools#4616 von longieirl, wird um 14:02 Uhr eingereicht.

  • 12:14:00: @cap-js/postgres@2.2.2 und @cap-js/db-service@2.10.1 werden veröffentlicht.

  • 13:31: Der cap-js-Maintainer chgeo antwortet: „Danke, dass Sie uns Bescheid geben. Wir bereinigen die Pakete mit höchster Priorität und untersuchen die Ursachen.“

  • 13:46: SAP veröffentlicht bereinigte Versionen nach dem Vorfall über den vertrauenswürdigen GitHub-Actions-OIDC-Publisher cap-npm: @cap-js/db-service@2.11.0, @cap-js/sqlite@2.4.0 und @cap-js/postgres@2.3.0 (mit dem abgestimmten Update @cap-js/hana@2.8.0).

  • 14:02:50: Der SAP-Entwickler patricebender erstellt cap-js/cds-dbs PR #1592. Damit wird die npm-Veröffentlichung von einer manuellen Freigabe abhängig gemacht; die oben zitierte Ursachenbeschreibung wird wörtlich wiedergegeben.

  • 14:24: Der Mitwirkende am cloud-mta-build-tool, kbarnold, antwortet: „Vielen Dank für den Bericht. Wir kümmern uns mit hoher Priorität darum.“

@cap-js/sqlite@2.2.2 wurde kurz nach der Entdeckung von npm entfernt. Für die übrigen schädlichen Versionen gelten npm-Warnhinweise: mbt@1.2.48 ist mit „SICHERHEIT: Diese Version enthält schädlichen Code. Nicht verwenden.“ gekennzeichnet, während bei den schädlichen Versionen von @cap-js/* „NICHT VERWENDEN. Diese Version enthält unbekannte Inhalte.“ steht. Entscheidend ist, dass mbt@1.2.48 zum Zeitpunkt der Erstellung dieses Beitrags weiterhin das latest-Dist-Tag für mbt trug. Eine bereinigte mbt-Version war noch nicht veröffentlicht worden. Ein einfaches npm install mbt installiert daher weiterhin das schädliche Tarball. Zum Zeitpunkt der Veröffentlichung war für keines der vier Pakete ein CVE-, GHSA- oder OSV-Datensatz angelegt. Die einzigen maßgeblichen öffentlichen Quellen sind die vier im Beitrag zitierten Hersteller-Blogs und die drei GitHub-Offenlegungsmeldungen.

Warum der Angriff „Mini“ Shai-Hulud heißt (und was tatsächlich anders ist)

Der Name Shai-Hulud wurde bereits bei zwei früheren npm-Supply-Chain-Vorfällen verwendet. Die ursprüngliche Shai-Hulud-Kampagne im September 2025 betraf @ctrl/tinycolor, ngx-bootstrap, ng2-file-upload und zahlreiche weitere abhängige Pakete (Snyks Zero-Day-Schwachstellenbericht dokumentierte den Verlauf in Echtzeit). Die Folgewelle SHA1-Hulud weitete sich im November 2025 auf mehr als 600 verschiedene Pakete aus, darunter Releases von Zapier, PostHog und Postman. Das Securelist-Team von Kaspersky veröffentlichte unabhängige technische Analysen zu beiden früheren Wellen (Erkennungsname HEUR:Worm.Script.Shulud.gen) unter securelist.com/shai-hulud-worm-infects-500-npm-packages und securelist.com/shai-hulud-2-0.

A Mini Shai-Hulud Has Appeared": Bun-Based Stealer Hits SAP @cap-js and mbt npm Packages

Shai-Hulud-NPM-Angriff: Behebung mit Snyk (kurze Anleitung zum Erkennen und Beheben von Shai-Hulud-betroffenen Abhängigkeiten in Ihren Projekten mithilfe der Snyk-CLI und der Advisor-Seiten).

Beide früheren Kampagnen zeigten wurmähnliches Verhalten: Die Payload stahl das npm-Token eines Opfers und nutzte es anschließend, um sich selbst in allen anderen Paketen zu veröffentlichen, für die das Token Schreibzugriff hatte. Auch die öffentliche Aufmerksamkeit entwickelte sich entsprechend: Der Wikipedia-Artikel über den Sandwurm aus Dune erreichte während der SHA1-Hulud-Offenlegung im November 2025 mit 2.772 Aufrufen seinen Höchststand (der höchste Tageswert in einem Datensatz über 16 Monate, etwa viermal so hoch wie der Durchschnitt des Artikels). Der Wikipedia-Artikel zum allgemeinen Thema „Supply-Chain-Angriff“ verzeichnete im April 2026, dem Monat von Mini Shai-Hulud, den höchsten monatlichen Durchschnitt seit Beginn der Aufzeichnungen: 310 Aufrufe pro Tag (laut Wikimedia REST API).

Die Kampagne vom 29. April greift das Shai-Hulud-Branding erneut auf (die Dead-Drop-Repositories tragen die Beschreibung als Namen). Die öffentlich verfügbaren Hinweise deuten bislang jedoch auf ein enger begrenztes Verhaltensspektrum hin:

  • Credential-Diebstahl: von mehreren Forschenden beobachtet und detailliert beschrieben.

  • Einschleusen von Persistenzmechanismen in Konfigurationen von Entwicklertools: neuartig und weiter unten beschrieben.

  • Automatisches Veröffentlichen von npm-Paketen: Der Code ist vorhanden und funktionsfähig, wie StepSecuritys statische Entschlüsselung zeigt. Die Payload sammelt npm-Token mit dem regulären Ausdruck /npm_[A-Za-z0-9]{36,}/g, prüft jedes Token über registry.npmjs.org/-/npm/v1/tokens (Filter: bypass_2fa: true und Schreibzugriff auf Organisationsebene), ermittelt die zugänglichen Pakete, ändert setup.mjs und execution.js in einer Kopie des Tarballs und veröffentlicht diese per direktem PUT an die npm-Registry – ohne die npm-CLI aufzurufen. Zum Zeitpunkt der Veröffentlichung wurde in freier Wildbahn kein fünftes Paket außerhalb der ursprünglichen vier mit der schädlichen Payload beobachtet. Die Wurmfunktion ist jedoch eine empirisch belegte Tatsache und keine Vermutung.

  • CI-Pipeline-Hijacking als Angriffsvektor: Die offizielle Stellungnahme von SAP in PR #1592 von patricebender für cap-js/cds-dbs (am selben Tag um 14:02 UTC eingereicht) lautet: „Am 29. April 2026 wurde das Repository bei einem Supply-Chain-Angriff kompromittiert – ein nicht autorisierter Akteur schob schädliche Commits ein, die den Release-Workflow kaperten und nicht autorisierte npm-Veröffentlichungen auslösten. Der Angreifer konnte kompromittierte Pakete veröffentlichen, weil der Workflow Veröffentlichungsrechte hatte und keine manuelle Freigabe erforderlich war.“ Die Abhilfe besteht darin, npm-Veröffentlichungen durch eine Umgebungsfreigabe zu schützen. Den Daten der npm-Registry zufolge wurden alle vier schädlichen Versionen über das Konto cloudmtabot veröffentlicht (dem legitimen Maintainer von mbt). SAPs bereinigte Versionen nach dem Vorfall wurden um 13:46 UTC über den vertrauenswürdigen GitHub-Actions-OIDC-Publisher cap-npm veröffentlicht, nicht über cloudmtabot. Das Konto cloudmtabot wurde inzwischen bei npm gesperrt. Die Kompromittierung von Maintainer-Zugangsdaten ist ein wiederkehrender Angriffsvektor bei dieser Art von Vorfällen. Die SAP-Stellungnahme benennt jedoch die fehlende Freigabe im Workflow ausdrücklich als strukturelle Hauptursache.

Der Diebstahl von Zugangsdaten ermöglicht die Selbstverbreitung über npm. Die unmittelbar beobachteten Aktivitäten sind jedoch Datenexfiltration und ein neuer Persistenzmechanismus. Die Abwehrmaßnahmen – Lockfile-Audit, Rotation von Zugangsdaten und Richtlinien für Lifecycle-Skripte – bleiben in jedem Fall dieselben.

So funktioniert der Angriff

Das Muster ist bei allen vier Paketen gleich: Das schädliche Tarball enthält die unveränderten Dateien des legitimen Pakets (sodass die CLI nach der Installation weiterhin funktioniert) und fügt zwei neue Dateien hinzu: setup.mjs (einen 4,5 KB großen Bun-Loader im Klartext, byte-identisch in allen vier Paketen) und execution.js (eine verschleierte Payload mit exakt 11.678.349 Byte; die Hashes unterscheiden sich zwischen mbt und den Paketen @cap-js/*). Nur bei mbt fügt die schädliche package.json außerdem drei Abhängigkeiten hinzu (axios, tar, unzip-stream), die im vorherigen, sauberen Release nicht enthalten waren. Die drei cap-js-Pakete ergänzten ihre bestehende package.json lediglich um den preinstall-Hook.

Ein kleines Loader-Skript während der Installation abzurufen und damit eine deutlich größere Laufzeitumgebung und Payload nachzuladen, ist ein Muster, das Snyk in diesem Jahr bereits an anderer Stelle beobachtet hat. Dazu gehört der axios-Vorfall mit einem plattformübergreifenden RAT, bei dem der Installations-Hook eine native Binärdatei über eine separate Abhängigkeit abrief.

Bei mbt sieht der Unterschied zwischen 1.2.47 (sauber) und 1.2.48 (schädlich) so aus:

// 1.2.47: no scripts block
// 1.2.48:
{
  "scripts": {
    "preinstall": "node setup.mjs"
  },
  "dependencies": {
    "axios": "^1.13.5",
    "tar": "^7.5.7",
    "unzip-stream": "^0.3.4"
  }
}

preinstall wird ausgeführt, bevor npm eine Ausgabe anzeigt. Außerdem kann die Ausführung nicht durch eine Richtlinie mit --ignore-scripts verhindert werden, wenn das Flag nicht gesetzt ist. Der Hook führt setup.mjs aus, das:

  1. Plattform und Architektur erkennt (einschließlich der Erkennung von Alpine/musl unter Linux).

  2. Über hasCommand("bun") prüft, ob sich bun bereits im PATH befindet. Falls ja, wird der Download übersprungen und die vorhandene Binärdatei verwendet. Andernfalls wird Bun 1.3.13 von GitHub Releases heruntergeladen (dabei werden HTTP-Weiterleitungen ohne Prüfung des Ziels verfolgt, wie Socket in seiner Analyse berichtet).

  3. Die Bun-Binärdatei wird bei einem Download in ein temporäres Verzeichnis entpackt.

  4. Ruft bun execution.js auf, um die verschleierte Payload auszuführen.

Sobald bun execution.js gestartet wird, durchläuft die Payload zwei Verschleierungsebenen: eine Zeichenfolgentabellen-Rotation im Stil von obfuscator.io (48.370 Einträge, dekodiert mithilfe eines nicht standardmäßigen Base64-Alphabets und durch eine Start-Prüfsumme abgesichert) sowie eine benutzerdefinierte Verschlüsselung, die StepSecurity „ctf-scramble-v2“ getauft hat und einen mit PBKDF2 abgeleiteten Masterschlüssel nutzt. Beide Ebenen wurden vollständig statisch entschlüsselt. Die entschlüsselte Laufzeitumgebung ist JavaScript, das unter Bun ausgeführt wird (ohne eingebetteten WASM- oder nativen Code; die Payload nutzt Bun-eigene APIs wie Bun.gunzipSync() und Bun.main).

StepSecurity beschreibt in seiner statischen Entschlüsselung folgende Verhaltensweisen der Payload:

  • Die Payload sammelt lokale Zugangsdaten, GitHub- und npm-Token, GitHub-Actions-Secrets, Cloud-Secrets aus AWS, Azure, GCP und Kubernetes, Token von CLI-Tools für Passwortmanager (1Password, Bitwarden, LastPass), ~/.claude.json und MCP-Serverkonfigurationen, Umgebungsvariablen mit Mustern wie KEY/TOKEN/SECRET/PASSWORD sowie auf dem Host gespeicherte Schlüssel für Krypto-Wallets. Außerdem fragt die Payload den AWS-Instanzmetadatendienst (169.254.169.254) ab, sofern er erreichbar ist.

  • Auf Linux-CI-Runnern startet es einen Python-Unterprozess, der /proc/{pid}/mem des GitHub-Actions-Prozesses Runner.Worker ausliest, um Geheimnisse im Klartext direkt aus dem Arbeitsspeicher des Runners auszulesen.

  • Unter Windows ruft es PowerShell mit -ExecutionPolicy Bypass auf.

  • Serialisiert die gestohlenen Daten als JSON, komprimiert sie mit gzip, verschlüsselt sie mit AES-256-GCM (32-Byte-Schlüssel, 12-Byte-IV) und verschlüsselt den AES-Schlüssel mit RSA-OAEP-SHA256 und einem eingebetteten öffentlichen RSA-4096-Schlüssel (gespeichert als gzip+base64-PEM am Dateioffset 9,429,992 in execution.js, zur Laufzeit mit Bun.gunzipSync() dekomprimiert). Das bedeutet: Verteidiger, die das Dead-Drop-Repository entdecken, können erkennen, dass etwas gestohlen wurde, aber nicht feststellen, was. Im Grunde muss jedes Zugangsmittel, auf das der Prozess zugreifen konnte, als offengelegt gelten.

  • Erstellt im GitHub-Konto des Opfers ein öffentliches Repository mit zufälligem Namen und der Beschreibung „A Mini Shai-Hulud has Appeared“ und hinterlegt dort den verschlüsselten Geheimtext als Dead Drop.

  • Prüft mithilfe der JavaScript-API Intl und POSIX-Umgebungsvariablen (LC_ALL, LC_MESSAGES, LANGUAGE, LANG) die Gebietsschemaeinstellungen des Systems. Wird ein russisches Gebietsschema (ru) erkannt, protokolliert die Schadsoftware "Exiting as russian language detected!" und beendet sich. Die Ausnahmen für die GUS-Region entsprechen dem dokumentierten Vorgehen von Cyberkriminellen in diesen Gebieten.

Der Persistenzmechanismus

Unabhängig davon, ob die Kampagne als Wurm eingestuft wird: Der Persistenzmechanismus ist das neuartigste Element, das in öffentlichen Berichten dokumentiert wurde.

Laut StepSecurity setzt die Schadsoftware drei Persistenz- und Ausführungsmechanismen ein:

  • Injektion in Konfigurationen von Entwicklertools. In jedes GitHub-Repository, in das das gestohlene Token schreiben kann, überträgt die Schadsoftware eine .claude/settings.json-Datei, die mit dem Claude Code-Hook SessionStart die Schadsoftware erneut ausführt, sobald ein Entwickler eine Claude-Code-Sitzung startet. Außerdem fügt sie eine .vscode/tasks.json mit "runOn": "folderOpen" hinzu, die beim Öffnen des Projekts in VS Code ausgelöst wird. Diese injizierten Dateien werden unter der Identität claude@users.noreply.github.com mit der Commit-Nachricht "chore: update dependencies" übertragen und können bei einer PR-Prüfung wie routinemäßige Automatisierungs-Commits wirken.

  • Injektion in GitHub-Actions-Workflows. Verfügt das gestohlene Token über den workflow-Scope, erstellt die Schadsoftware den typosquatteten Branch dependabout/github_actions/format/setup-formatter (beachten Sie das fehlende t) und überträgt die Datei .github/workflows/format-check.yml, wobei sie das Dependabot-Dienstkonto imitiert (dependabot[bot]@users.noreply.github.com, Commit-Nachricht "Add formatter workflow"). Der injizierte Workflow verwendet ${{ toJSON(secrets) }}, um alle Repository-Geheimnisse in ein Build-Artefakt namens format-results.txt zu schreiben.

  • Daemonisierung auf Entwicklerrechnern. Auf Hosts außerhalb von CI forkt sich die Schadsoftware als abgekoppelter Hintergrundprozess mit der Umgebungsvariable __DAEMONIZED=1. Anschließend wird der übergeordnete Prozess sauber beendet, sodass npm install ohne sichtbare Fehlermeldung zum Benutzer zurückkehrt. Der abgekoppelte Kindprozess läuft ohne erkennbare Prozessabstammung weiter.

Damit erweitert sich die Liste der in npm-Supply-Chain-Kampagnen beobachteten Persistenzvektoren bei der Installation um Konfigurationsdateien von KI-Coding-Agenten, neben package.json-Lifecycle-Hooks, CI-Workflows und IDE-Plugin-Manifesten.

Angriffe auf KI-Agent-Konfigurationen sind bereits dokumentiert und keine Premiere. Microsofts VSCode #309406 zum tasks.json-Vektor runOn: folderOpen wurde sechzehn Tage zuvor eingereicht und als „By Design“ geschlossen (Workspace Trust gilt als ausreichende Gegenmaßnahme, obwohl die Vertrauensprüfung keine Commits in bereits vertrauenswürdige Repositories abdeckt). Anthropic erhielt zwölf Tage zuvor den Bericht claude-code #49778 zum SessionStart-Hook. Er ist weiterhin offen und bislang ohne Antwort von Anthropic; als Präzedenzfall aus der Praxis wird das Cozempic-Supply-Chain-Audit angeführt. Der Trivy-KI-Agent-Kompromiss (CVE-2026-28353) im März 2026 ging noch weiter: Mit gestohlenen Tokens wurde eine manipulierte VS-Code-Erweiterung veröffentlicht, die auf fünf verschiedene KI-Coding-Agenten abzielte. Snyk hat diese Überschneidung auch in einem separaten Beitrag zu Clinejection behandelt. Mini Shai-Hulud ist ein weiterer Datenpunkt in diesem Muster, nicht der erste.

Kompromittierungsindikatoren

Diese Liste fasst öffentliche Berichte von StepSecurity, Aikido, Socket und SafeDep zusammen. Die vollständigen IOCs und forensischen Details finden Sie in den jeweiligen Berichten. Jede schädliche Version ist weiterhin als unveränderlicher Eintrag in der npm-Registry abrufbar: registry.npmjs.org/mbt/1.2.48, registry.npmjs.org/@cap-js/sqlite/2.2.2, registry.npmjs.org/@cap-js/postgres/2.2.2 und registry.npmjs.org/@cap-js/db-service/2.10.1. Der Veröffentlichungszeitpunkt und der Fingerabdruck "preinstall": "node setup.mjs" sind in jedem Eintrag erhalten.

Compromised npm artifacts
  mbt@1.2.48                       shasum 0af7415d65753f6aede8c9c0f39be478666b9c12
  @cap-js/db-service@2.10.1        shasum 4b04304f6d51392e3f43856c94ca95800518a694
  @cap-js/sqlite@2.2.2             shasum 7b6a28e92149637e5d7c7f4a2d3e54acd507c929
  @cap-js/postgres@2.2.2           shasum e80824a19f48d778a746571bb15279b5679fd61c

Compromised npm publisher account
  cloudmtabot (used to publish all four malicious versions)

Files added to the compromised tarballs
  setup.mjs       ~4.5 KB plaintext Bun loader, byte-identical
                   across all four packages
  execution.js    11,678,349 bytes obfuscated payload, hash
                   differs per package

File hashes (SHA-256, per StepSecurity)
  setup.mjs (all packages)
    4066781fa830224c8bbcc3aa005a396657f9c8f9016f9a64ad44a9d7f5f45e34
  execution.js (mbt@1.2.48)
    80a3d2877813968ef847ae73b5eeeb70b9435254e74d7f07d8cf4057f0a710ac
  execution.js (@cap-js/sqlite@2.2.2)
    6f933d00b7d05678eb43c90963a80b8947c4ae6830182f89df31da9f568fea95
  Embedded /proc/mem dumper
    29ac906c8bd801dfe1cb39596197df49f80fff2270b3e7fbab52278c24e4f1a7

In-payload indicators (recovered by StepSecurity static analysis)
  Custom cipher salt              ctf-scramble-v2
  PBKDF2 input key                5012caa5847ae9261dfa16f91417042f367d6bed149c3b8af7a50b203a093007
  Derived master key              fd4b0f07b27e8f41bc70b8e2b79d168fb3fe80d7e0b37f43c506136a3418b44d
  CIS evasion log string          Exiting as russian language detected!
  Daemonization env var           __DAEMONIZED
  GitHub PAT regex                /gh[op]_[A-Za-z0-9]{36}/g
  npm token regex                 /npm_[A-Za-z0-9]{36,}/g

Network and runtime indicators
  - Outbound request to github.com/oven-sh/bun/releases/download/bun-v1.3.13/{asset}.zip
    where {asset} is one of:
      bun-linux-aarch64
      bun-linux-x64-baseline
      bun-linux-x64-musl-baseline
      bun-darwin-aarch64
      bun-darwin-x64
      bun-windows-aarch64
      bun-windows-x64-baseline
    (skipped if `bun` is already on PATH)
  - Process chain during install:
    node setup.mjs -> bun execution.js
  - Linux CI runners: child Python process reading
    /proc/{pid}/mem of Runner.Worker
  - Windows: powershell -ExecutionPolicy Bypass
  - api.github.com calls:
    POST /user/repos               (dead-drop repo creation)
    GET  /search/commits?q=OhNoWhatsGoingOnWithGitHub
                                   (P2P token dead-drop search)
  - Direct PUT to registry.npmjs.org during self-propagation
    (no npm CLI involvement)
  - Cloud metadata reads:
    http://169.254.169.254          (AWS/Azure IMDS)
    http://169.254.170.2            (ECS task metadata)
    http://[fd00:ec2::254]          (AWS IMDSv2 IPv6)

GitHub-side indicators
  - New public repositories on developer accounts with the
    description string "A Mini Shai-Hulud has Appeared"
  - Repository names follow a Dune-themed pattern, regex:
    (sardaukar|mentat|fremen|atreides|harkonnen|gesserit|
     prescient|fedaykin|tleilaxu|siridar|kanly|sayyadina|
     ghola|powindah|prana|kralizec)-(sandworm|ornithopter|
     heighliner|stillsuit|lasgun|sietch|melange|thumper|
     navigator|fedaykin|futar|slig|phibian|laza|cogitor|
     ghola)-\d{1,3}
  - Commits authored by claude@users.noreply.github.com
    with the message "chore: update dependencies"
  - New or modified .claude/settings.json files containing
    a SessionStart hook
  - New or modified .vscode/tasks.json with a task using
    "runOn": "folderOpen"
  - P2P token dead-drop commits referencing the string
    "OhNoWhatsGoingOnWithGitHub" (used by the malware to
    locate base64-encoded tokens left by other victims)
  - Typosquatted Dependabot branch:
    dependabout/github_actions/format/setup-formatter
  - Injected workflow file .github/workflows/format-check.yml
    using the expression toJSON(secrets), authored by
    dependabot[bot]@users.noreply.github.com with commit
    message "Add formatter workflow", uploading artifact
    "format-results.txt"

Live-GitHub-Suchen nach den beiden charakteristischen Zeichenfolgen:

Jedes Dead-Drop-Repository enthält eine einzelne README.md sowie eine oder mehrere Dateien unter results/results-<unix-ms>-<counter>.json. Externe Forschende haben durch die direkte Untersuchung eines aktiven Opfer-Repositorys das Dateiformat bestätigt:

{"envelope": "<base64 AES-256-GCM ciphertext>", "key": "<base64 RSA-4096 wrapped session key>"}

Da der Schlüssel zur Verschlüsselung der RSA-4096-Public-Key des Angreifers ist, können Verteidiger die Inhalte selbst mit vollem Zugriff auf das GitHub-Konto des Opfers nicht lesen.

Was Sie tun sollten

Das Ausmaß des Schadens hängt davon ab, ob Ihre Build-Pipelines oder Entwicklerrechner im Zeitraum der Gefährdung (ungefähr von 10:00 bis 14:00 UTC am 29. April 2026 sowie solange die veralteten Versionen noch auflösbar sind) für eine der vier betroffenen Versionen npm install ausgeführt haben.

Prüfen Sie Ihre Installationen. Durchsuchen Sie Lockdateien nach den betroffenen Versionen und achten Sie auf transitive Abhängigkeiten: @cap-js/sqlite@2.2.2 deklariert @cap-js/db-service@^2.10.0 als Abhängigkeit. Eine saubere Installation von @cap-js/sqlite aus einem verfügbaren Versionsbereich kann daher @cap-js/db-service@2.10.1 (die schädliche Version) transitiv installieren, ohne dass jemand sie direkt aufgeführt hat.

# in any project root
rg -n '"mbt"|"@cap-js/db-service"|"@cap-js/sqlite"|"@cap-js/postgres"' \
   package-lock.json npm-shrinkwrap.json yarn.lock pnpm-lock.yaml 2>/dev/null

Für Snyk-Kunden machen snyk test und snyk monitor die schädlichen Versionen anhand der vier oben genannten Advisories sichtbar. Auch die Seiten der Snyk Security Database für mbt, @cap-js/db-service, @cap-js/sqlite und @cap-js/postgres enthalten Informationen zu diesem Sicherheitsvorfall.

Wenn eine kompromittierte Version installiert wurde:

  • Betrachten Sie alle Zugangsdaten, auf die von diesem Rechner oder dieser Pipeline aus zugegriffen werden konnte, als offengelegt. Da die Verschlüsselung mit dem RSA-Schlüssel des Angreifers erfolgt, können Verteidiger den Inhalt des Dead Drops nicht auslesen und den Umfang des Vorfalls nicht bestätigen. Gehen Sie beim Erneuern daher vorsichtshalber umfassend vor. Die 134 Dateipfadmuster, die StepSecurity aus der Schadsoftware extrahiert hat, umfassen mindestens: npm-Veröffentlichungstokens (höchste Priorität, da diese eine wurmartige Verbreitung über andere Pakete ermöglichen, die ein Entwickler betreut), GitHub-PATs und OAuth-Berechtigungen, AWS-/Azure-/GCP-Zugangsdaten sowie alle Rollen, die vom betroffenen Rechner aus übernommen werden können, Kubernetes-kubeconfigs (~/.kube/config, k3s-YAML, Service-Account-Tokens in Pods), Docker-Konfigurationen (~/.docker/config.json), Terraform-Cloud-Zugangsdaten (~/.terraform.d/credentials.tfrc.json), Helm-Konfiguration, SSH-Schlüssel (~/.ssh/id*, config, known_hosts, Host-Schlüssel unter /etc/ssh/), CLI-Tokens für Passwortmanager (1Passwords op, Bitwardens bw, LastPass), .npmrc / .pypirc / .yarnrc, .gitconfig und .git-credentials, Shell-Verlaufsdateien, Umgebungsvariablen und .env*-Dateien mit Mustern wie *_TOKEN, *_KEY, *_SECRET oder *_PASSWORD, ~/.claude.json und alle MCP-Server-Konfigurationen (einschließlich Kiro-MCP-Konfigurationen unter ~/.kiro/settings/mcp.json), Sitzungsdaten von Messaging-Apps (Signal, Slack-Cookies, Discord, Telegram, Element, Pidgin), VPN-Konfigurationen (NordVPN, ProtonVPN, OpenVPN usw.), FileZilla-Serverlisten, Ansible-Konfigurationen sowie Wallet-Schlüssel für Bitcoin, Ethereum, Monero, Dash, Zcash, Dogecoin, Litecoin, Electrum, Exodus, Ledger Live und Atomic. Die Schadsoftware liest außerdem AWS-Instanzmetadaten (169.254.169.254, 169.254.170.2, fd00:ec2::254) und ECS-Task-Metadaten aus. Daher müssen alle IAM-Rollen, die über diese Endpunkte erreichbar sind, ebenfalls als offengelegt gelten.

  • Prüfen Sie, welchen GitHub-Actions-Geheimnissen Zugriff ermöglicht wurde. Die Extraktionstechnik über /proc/{pid}/mem liest den gesamten lesbaren Adressraum von Runner.Worker aus. Damit sind alle Geheimnisse betroffen, die bis zu diesem Zeitpunkt im Workflow verwendet wurden – auch wenn der Installationsschritt nicht direkt auf sie verweist. Standardmäßig blockieren von GitHub gehostete Runner diesen Zugriff nicht; zur Erkennung ist ein Sicherheitsagent auf dem Runner erforderlich, etwa StepSecurity Harden-Runner.

  • Durchsuchen Sie Ihre GitHub-Organisation nach den IOCs aus dem obigen Codeblock: Dead-Drop-Repositories mit dem Dune-inspirierten Namensschema und der Beschreibung „Mini Shai-Hulud“, die Autorensignatur claude@users.noreply.github.com, die Imitation von dependabot[bot]@users.noreply.github.com auf einem dependabout/...-Branch, der injizierte .github/workflows/format-check.yml-Workflow, der toJSON(secrets) in ein format-results.txt-Artefakt exfiltriert, die P2P-Token-Dead-Drop-Commit-Zeichenfolge OhNoWhatsGoingOnWithGitHub sowie unerwartete Ergänzungen in .claude/settings.json oder .vscode/tasks.json.

  • Fixieren Sie saubere Versionen. Verwenden Sie für die drei @cap-js-Pakete vorzugsweise die nach dem Vorfall veröffentlichten Versionen von SAP (@cap-js/db-service@2.11.0, @cap-js/sqlite@2.4.0, @cap-js/postgres@2.3.0) als Zielversionen und die Versionen von vor dem Vorfall (2.10.0, 2.2.1 bzw. 2.2.1) als Mindestversionen. Für mbt war zum Zeitpunkt der Veröffentlichung noch keine bereinigte Version verfügbar. Fixieren Sie die Version daher auf mbt@1.2.47, bis SAP eine Nachfolgeversion veröffentlicht.

Allgemeine Härtungsmaßnahmen:

Sichern Sie Ihre Python-Apps ab

Finden und beheben Sie Python-Schwachstellen – kostenlos mit Snyk.

Keine Kreditkarte erforderlich.

Oder registrieren Sie sich mit Azure AD Docker ID Bitbucket

Mit der Nutzung von Snyk erklären Sie sich mit unseren Richtlinien einverstanden, einschließlich unserer Nutzungsbedingungen und Datenschutzerklärung.