LiteLLM piégé : quand un scanner CI corrompu prend le contrôle de la passerelle LLM
En mars 2026, des attaquants ont volé le jeton de publication PyPI de LiteLLM en compromettant Trivy dans son pipeline CI, puis ont diffusé deux versions piégées. La chaîne montre pourquoi la passerelle LLM est une cible de choix.
Ce qui s’est passé
Le 24 mars 2026, deux versions malveillantes du paquet Python litellm — 1.82.7 et 1.82.8 — ont été publiées sur PyPI par un acteur suivi sous le nom de TeamPCP. LiteLLM est la bibliothèque de passerelle de modèles qui se trouve sous CrewAI, DSPy, MLflow, OpenHands et des dizaines d’autres frameworks d’agents, téléchargée plusieurs millions de fois par jour. Les paquets sont restés en ligne environ trois heures avant leur mise en quarantaine par PyPI, selon l’analyse de Snyk et Help Net Security.
Les attaquants n’ont jamais exploité de faille dans le code de LiteLLM lui-même. Ils ont obtenu le jeton PYPI_PUBLISH du projet en compromettant d’abord Trivy, un scanner open source exécuté dans le pipeline CI de LiteLLM. C’est un cas d’école d’attaque par la chaîne d’outils : empoisonner une dépendance de build de confiance, récupérer le secret qu’elle peut lire, et publier une version malveillante légitimement signée.
Comment ça marche
La chaîne s’est déroulée sur cinq jours, et chaque saut a réutilisé la même infrastructure d’exfiltration (une clé RSA partagée et un nom d’archive tpcp.tar.gz confirmés sur l’ensemble des opérations par Wiz et Unit 42) :
- 19 mars — TeamPCP a réécrit des tags Git dans le dépôt
trivy-actionpour faire pointer un tag de version vers une version malveillante, après avoir volé les identifiants d’automatisation d’Aqua via un workflowpull_request_target(« Pwn Request ») qui récupère et exécute du code de fork non fiable. - 23 mars — Le même scénario a frappé Checkmarx KICS ; le domaine C2
checkmarx.zoneet le domaine d’exfiltrationmodels.litellm.cloudont été enregistrés. - 24 mars — La CI de LiteLLM a exécuté le Trivy empoisonné depuis
apt, sans version épinglée. L’action compromise a lu le jetonPYPI_PUBLISHdans l’environnement du runner, et les attaquants l’ont utilisé pour publier les deux versions piégées.
La charge utile elle-même était un voleur d’identifiants en trois étapes : collecte de secrets (clés SSH, fichiers .env, identifiants cloud et Kubernetes, phrases de récupération de portefeuilles), chiffrement et envoi (POST) vers le domaine d’exfiltration, puis installation d’un service utilisateur systemd pour la persistance et tentative de mouvement latéral entre les namespaces Kubernetes. La version 1.82.8 a renforcé la livraison avec un hook de démarrage .pth — un fichier placé dans site-packages/ qui s’exécute à chaque lancement de l’interpréteur Python, y compris pip install lui-même, sans aucun import requis. Comme le paquet était signé avec des identifiants légitimes mais volés, il a passé sans encombre la vérification de hash de pip. Nous omettons volontairement le détail interne de la charge utile ; les enseignements défensifs ci-dessous n’en ont pas besoin.
Détail notable : une partie du ciblage de la campagne a été pilotée par un bot d’attaque autonome. StepSecurity a documenté hackerbot-claw, un compte GitHub se décrivant comme un « agent autonome de recherche en sécurité », qui scannait des dépôts et ouvrait des pull requests d’exploitation contre des projets de Microsoft, DataDog et de la CNCF sur une fenêtre de dix jours — l’un des premiers cas observés d’un agent IA pilotant opérationnellement des intrusions par la chaîne d’approvisionnement.
Pourquoi c’est important
La passerelle LLM devient le magasin de secrets le plus concentré d’une pile IA. Un routeur comme LiteLLM se voit confier, par conception, les clés d’API de chaque fournisseur de modèles qu’il dessert, plus l’environnement de l’hôte qui l’exécute. Compromettre cette seule position permet d’intercepter les secrets de toute la flotte sans violer aucun fournisseur en amont — précisément le levier visé par TeamPCP. Help Net Security et Unit 42 soulignent le schéma plus large : la campagne a délibérément ciblé des outils de sécurité (Trivy, Checkmarx) parce que les scanners disposent d’un large accès en lecture aux pipelines où ils s’exécutent. Votre outillage défensif fait partie de votre surface d’attaque.
Défenses
- Épinglez chaque dépendance CI par empreinte, pas par tag. Les tags Git sont mutables ; épinglez les GitHub Actions et les outils en ligne de commande à un SHA de commit ou à un hash de contenu pour qu’un tag réécrit ne puisse pas glisser silencieusement une version malveillante.
- Verrouillez
pull_request_target. Ne récupérez et n’exécutez jamais de code de fork non fiable dans un workflow privilégié. Utilisezpull_requestpour la CI des forks, conditionnez les jobs privilégiés à une approbation manuelle, et limitezGITHUB_TOKENà la lecture seule. - Restreignez les identifiants de publication. Préférez le Trusted Publishing PyPI (basé sur OIDC, à durée de vie courte) aux jetons
PYPI_PUBLISHà longue durée de vie, et isolez l’étape de publication des étapes qui exécutent des outils tiers. - Surveillez le trafic réseau sortant pendant le build. Mettez en liste blanche les destinations sortantes des runners, afin qu’un
curlinattendu vers un domaine inconnu soit bloqué et signalé, et non exécuté en silence. - Détectez les hooks de démarrage
.pth. La seule vérification de hash ne détecte pas un paquet malveillant mais validement signé. Signalez toute dépendance qui installe un fichier.pthcontenantexec,subprocessoubase64. - Si vous avez exécuté 1.82.7 ou 1.82.8 : considérez l’hôte comme compromis, épinglez à
<=1.82.6(ou une version propre ultérieure), faites tourner tous les identifiants accessibles, et recherchez le service de persistance ainsi que les pods Kubernetes nommésnode-setup-*.
Statut
| Élément | État |
|---|---|
Versions litellm affectées | 1.82.7, 1.82.8 — mises en quarantaine et retirées de PyPI |
| Versions sûres | ≤ 1.82.6, plus les versions propres après rotation des clés (24 mars) |
| Cause racine | Vol du jeton PYPI_PUBLISH via Trivy empoisonné dans la CI |
| Divulgation | FutureSearch a donné l’alerte le 24 mars 2026 ; clés tournées le jour même |
| Campagne élargie | TeamPCP a aussi touché Trivy (19 mars) et Checkmarx KICS (23 mars) |
Dates et détails techniques issus de Snyk (24 mars 2026), Help Net Security (25 mars 2026), Palo Alto Unit 42 et StepSecurity. Les numéros de version et les indicateurs d’infrastructure reflètent les conclusions publiées par ces fournisseurs.