Le 21 octobre 2026, une version piégée de LiteLLM, la passerelle open source très utilisée pour accéder aux modèles d’IA, a été publiée sur PyPI et Docker Hub par le pipeline officiel du projet. L’analyse de cause racine publiée le 23 octobre par LiteLLM remonte à une erreur banale : une clé d’administration poussée par erreur dans un dépôt public en mai, supprimée du fichier mais jamais révoquée. Cinq mois plus tard, cette clé a ouvert à l’attaquant l’accès à un jeton GitHub de propriétaire d’organisation, puis à la chaîne de publication. Une leçon directe pour toutes les équipes qui déploient des agents IA dotés d’identifiants.
- Une clé maîtresse d’une plateforme d’agents interne, exposée le 27 mai 2026 dans un dépôt GitHub public, n’a jamais été révoquée.
- Le 10 octobre, l’attaquant l’a utilisée pour récupérer le jeton OAuth GitHub CLI d’un propriétaire de l’organisation, puis a exfiltré les secrets CI et les jetons de deux autres mainteneurs.
- Le 21 octobre, il a contourné la protection de branche et publié
litellm==1.107.0(7 wheels PyPI) ainsi que des images Docker compromises. - Le code malveillant s’exécute à chaque démarrage de Python, même sans importer LiteLLM, et vole identifiants cloud, clés SSH, secrets CI, clés d’API des fournisseurs d’IA et configurations d’outils de développement IA.
- Tout hôte ayant installé 1.107.0 doit être considéré comme compromis : désinstaller le paquet ne suffit pas.
La chaîne d’attaque
LiteLLM a qualifié son analyse du 23 octobre de « source de vérité canonique ». Elle remplace les hypothèses provisoires de l’avis d’incident du 21 octobre. La chaîne tient en sept étapes.
| Date (UTC) | Étape |
|---|---|
| 27 mai, 18:53 | Un fichier opencode.json contenant une clé d’administration de la LiteLLM Agent Platform est commité dans le dépôt public LiteLLM-Labs/lite-harness. Il est supprimé trois heures plus tard, mais reste dans l’historique et la clé n’est pas révoquée. |
| 10 octobre, 21:13–21:28 | L’attaquant appelle l’API de la plateforme d’agents ; une requête de listing des agents renvoie le jeton GitHub CLI d’un propriétaire de l’organisation. |
| 10 octobre, 22:11–22:14 | Des workflows poussés sur des branches temporaires envoient les secrets CI (dont GH_TOKEN et RELEASE_PLEASE_TOKEN) vers un point de terminaison webhook.site, puis les exécutions sont supprimées. |
| 12 octobre | Les secrets de plusieurs dépôts privés sont exfiltrés de la même manière. |
| 21 octobre, 10:08 | Une modification du workflow de publication, rejetée par la protection de branche, est forcée avec le jeton du propriétaire. Elle permet de construire la version depuis le fork sosie Berri-AI/litellm. |
| 21 octobre, 11:11–11:47 | Le portail d’approbation de production est validé avec le jeton d’un deuxième mainteneur ; sept wheels 1.107.0 puis les images Docker Hub et GHCR sont publiées. |
| 21 octobre, 11:53–11:54 | Les traces d’exécution sont supprimées avec le jeton d’un troisième mainteneur. |
| 21 octobre, 12:06 → 14:20 | Un chercheur d’Upwind Security signale la compromission ; PyPI met le paquet en quarantaine vers 13:23 et les tags Docker sont retirés ou réorientés à 14:20. |
Pourquoi une simple clé a suffi
La LiteLLM Agent Platform est un projet expérimental d’agents cloud auto-hébergés qui ouvrent des pull requests. Pour cela, elle détenait non pas un jeton à périmètre restreint, mais le jeton OAuth GitHub CLI d’un propriétaire de l’organisation. Selon LiteLLM, ce type de jeton n’est pas limité en périmètre, est émis après la 2FA et n’est pas soumis à la réauthentification exigée pour les actions sensibles. Compromettre l’agent revenait donc à obtenir les droits de propriétaire.
Deux autres facteurs ont aggravé la situation. Le workflow de publication acceptait désormais un propriétaire de source arbitraire, ce qui a permis de construire depuis un fork sosie. Et la règle d’approbation des releases avait été assouplie la semaine même : deux ingénieurs quelconques suffisaient, au lieu d’un compte dédié lié à un appareil physique.
Analyse de la charge malveillante
Selon l’analyse de Corgea, l’attaquant a ajouté un répertoire cook aux données de construction du paquet. Les wheels installaient ainsi à la racine de site-packages trois fichiers : cook.pth, cook.py et sitecustomize.py. Le source et le tag officiel restaient propres, ce qui rendait la modification invisible dans le code.
Exécution et persistance
Le fichier .pth est exécuté par Python à chaque démarrage de l’interpréteur : le voleur tourne même si LiteLLM n’est jamais importé. sitecustomize.py lance en plus un démon détaché (verrou /tmp/remote_code_loader.lock) qui, toutes les heures, récupère un nom d’hôte depuis un fichier GitHub, télécharge du code Python et l’exécute. Aucun second étage n’a été observé à ce jour.
Ce qui est volé
Mots de passe et cookies de navigateurs, clés SSH, GPG et TLS, identifiants AWS, GCP et Azure (y compris via les services de métadonnées), secrets Docker et Kubernetes, configurations CI, jetons Vault, identifiants de registres de paquets, variables d’environnement et configurations d’outils de développement IA. Spécificité LiteLLM : le code interroge la table des identifiants du proxy, qui contient les clés d’API des fournisseurs de modèles. Les données sont chiffrées (AES-256 et RSA-4096) puis envoyées vers litellm.dev, un domaine sosie du légitime litellm.ai.
Pourquoi c’est important
LiteLLM se situe au cœur des architectures IA : il concentre, par construction, les clés d’API de tous les fournisseurs de modèles d’une organisation. Le compromettre, c’est obtenir un trousseau complet. Mais la leçon dépasse ce projet. Un agent IA qui agit sur vos dépôts détient des identifiants, et ces identifiants deviennent la cible. Un jeton surdimensionné confié à un agent expérimental a suffi à transformer une fuite de configuration oubliée en compromission de la chaîne d’approvisionnement logicielle.
Enfin, la suppression d’un fichier ne révoque rien. Un secret poussé dans un dépôt public doit être considéré comme compromis dès la première seconde.
Lecture MITRE ATT&CK
Les sources ne fournissent pas de correspondance ATT&CK. Le tableau ci-dessous est une lecture indicative de Defensy, fondée sur les comportements décrits.
| Technique | Comportement observé |
|---|---|
| T1593.003 — Search Open Websites/Domains: Code Repositories | Clé d’administration récupérée dans l’historique d’un dépôt public |
| T1078 — Valid Accounts | Utilisation de la clé maîtresse puis des jetons de mainteneurs |
| T1528 — Steal Application Access Token | Vol du jeton OAuth GitHub CLI et des secrets CI |
| T1567.004 — Exfiltration Over Webhook | Secrets CI envoyés vers webhook.site |
| T1070 — Indicator Removal | Suppression des exécutions de workflows |
| T1195.002 — Compromise Software Supply Chain | Publication de 1.107.0 par le pipeline officiel |
| T1546 — Event Triggered Execution | Exécution à chaque démarrage de Python via .pth et sitecustomize.py |
| T1552.005 — Cloud Instance Metadata API | Requêtes vers les services de métadonnées cloud |
Recommandations
- ImmédiatVérifier l’exposition à 1.107.0
Cherchez
Version: 1.107.0dans les métadonnées installées, les fichierscook.pth,cook.pyetsitecustomize.pydans site-packages, ainsi que/tmp/remote_code_loader.lock. Contrôlez les images tirées le 21 octobre avec les tagslatest,main-latestoumain-stable. - ImmédiatTraiter les hôtes touchés comme compromis
Isolez-les, arrêtez le chargeur, reconstruisez environnements et images à partir de sources saines en épinglant une version vérifiée (1.106.2 ou une version confirmée saine par LiteLLM) et les images par digest.
- ImmédiatFaire tourner tous les secrets exposés
Clés des fournisseurs d’IA stockées dans le proxy, identifiants cloud, Kubernetes, CI, registres, SSH et outils IA. Examinez CloudTrail et les journaux équivalents à partir du 21 octobre 11:39 UTC, et le trafic sortant vers
litellm.dev. - Court termeRéduire les droits des agents IA
Donnez à chaque agent un compte de service dédié et des jetons à périmètre minimal, jamais le jeton personnel d’un administrateur. Inventoriez les identifiants détenus par vos agents et plateformes d’automatisation.
- Court termeRévoquer d’abord, nettoyer ensuite
Activez la détection de secrets à la source (push protection) et formalisez une procédure : tout secret exposé est révoqué immédiatement, même si le commit a été supprimé.
- Moyen termeDurcir votre propre chaîne de publication
Interdisez aux administrateurs de contourner la protection de branche, figez le dépôt source des workflows de release, vérifiez la provenance et comparez le contenu des paquets avec la version précédente (alerte sur tout nouveau
.pth). - Moyen termeÉpingler les dépendances
Utilisez des fichiers de verrouillage avec empreintes et des images référencées par digest plutôt que des versions flottantes.
Cet incident n’a rien d’exotique : un secret oublié, un jeton trop puissant, un agent IA mal cloisonné. C’est précisément pourquoi il doit alerter. Les agents IA sont des identités à privilèges et doivent être gouvernés comme tels.
Notre offre Adoption sécurisée de l’IA vous aide à cadrer les droits et les secrets de vos agents et passerelles LLM. Notre équipe SOC, Détection & Réponse peut vous accompagner dans la recherche de compromission et la rotation des secrets.
- The attack chain behind the v1.107.0 LiteLLM releaseLiteLLM — O. Jensen, M. Wang — 23 octobre 2026
- LiteLLM 1.107.0 PyPI and Docker compromise (cook.pth, sitecustomize)Corgea — 22 octobre 2026, mis à jour le 24 octobre
- The Unrevoked Key: Agent Credential to LiteLLM Release HijackCloud Security Alliance Labs — octobre 2026
- Leaked LiteLLM master key let attackers hijack the release pipelineThe Hacker News — octobre 2026
