Skip to content

LiteLLM : Comment un Scanner de Sécurité Empoisonné a Piraté Tout un Écosystème IA

LiteLLM : Comment un Scanner de Sécurité Empoisonné a Piraté Tout un Écosystème IA

Le 24 mars 2026, à 10h39 UTC, deux versions malveillantes de LiteLLM apparaissaient sur PyPI. Le package est téléchargé 3,4 millions de fois par jour. Les versions compromises sont restées en ligne environ trois heures avant que PyPI ne quarantaine le package. C'est suffisant pour potentiellement compromettre des dizaines de milliers de systèmes. Mais ce qui rend cette attaque fascinante, c'est comment les attaquants ont obtenu les accès : en piratant le scanner de sécurité censé protéger le pipeline.

L'attaquant, connu sous le nom de TeamPCP, n'est pas un acteur nouveau. C'est un groupe coordonné qui mène une campagne supply chain depuis plusieurs semaines. Et leur méthode est d'une élégance méchante : compromettre les outils de sécurité pour compromettre les projets qui les utilisent. C'est l'équivalent numérique de voler les clés du gardien de nuit.

La chaîne d'attaque commence le 19 mars avec Trivy, le scanner de sécurité open source d'Aqua Security. Les attaquants ont réécrit les tags Git du dépôt GitHub Action de Trivy pour pointer vers une version malveillante (v0.69.4) contenant un payload de récupération de credentials. Quand LiteLLM, qui utilise Trivy dans son pipeline CI/CD, a exécuté le scanner compromis, les credentials du mainteneur LiteLLM ont été volées. C'est la porte d'entrée.

Le 23 mars, les attaquants activent un deuxième volet : ils compromettent aussi le GitHub Action KICS de Checkmarx et enregistrent deux domaines C2 : checkmarx.zone et models.litellm.cloud. Le deuxième domaine est particulièrement insidieux — il imite un sous-domaine légitime du projet LiteLLM, ce qui rend l'exfiltration de données beaucoup plus difficile à détecter dans les logs réseau.

Le 24 mars à 10h39, la première version malveillante (1.82.7) est publiée sur PyPI. Treize minutes plus tard, à 10h52, une deuxième version (1.82.8) est publiée avec un mécanisme de livraison encore plus agressif. Les deux contiennent un payload en trois étapes : un collecteur de credentials, un système d'exfiltration chiffré, et un backdoor persistant avec un ver Kubernetes.

Le mécanisme de livraison est clever. Les attaquants utilisent un fichier .pth dans site-packages/, un mécanisme Python qui s'exécute automatiquement à chaque démarrage de l'interpréteur. Le fichier litellm_init.pth fait 34 628 octets, encodé en double base64. Il spawn un processus Python enfant qui, lui aussi, déclenche l'exécution du .pth, créant un effet de fork bomb non intentionnel. C'est d'ailleurs comme ça que l'attaque a été découverte : Callum McMahon de FutureSearch testait un plugin Cursor MCP qui tirait LiteLLM comme dépendance transitive. Son PC est devenu indisponible à cause de l'épuisement de la RAM. En traçant le problème, il a trouvé le fichier .pth et a compris que LiteLLM avait été backdooré.

La réaction a été rapide. McMahon a ouvert un issue GitHub à 11h48. Le thread a atterri sur Hacker News où il a atteint 324 points. Pendant ce temps, les attaquants ont inondé l'issue avec des bots et l'ont fermée en utilisant le compte compromis du mainteneur. À 15h09, le mainteneur légitime confirmait que toutes les clés GitHub, Docker et PyPI avaient été rotées. Les versions compromises ont été supprimées et le package déquarantiné.

Ce qui rend cette attaque significative, c'est la chaîne de confiance qu'elle brise. Trivy est utilisé par des milliers de projets pour scanner leurs dépendances. En compromettant Trivy, TeamPCP a obtenu un accès potentiel à l'ensemble de l'écosystème Python, pas juste à LiteLLM. Le fait que l'attaque ait touché LiteLLM en premier est probablement lié à la popularité massive du package dans la communauté IA — c'est une cible de choix.

Pour nous, l'incident a eu des conséquences directes. C'est l'attaque qui a déclenché la mise en place du système d'audit de sécurité quotidien sur notre infrastructure. Le 24 mars, quand l'alerte a éclaté, on a découvert que litellm était dans un virtualenv du serveur. Le package n'a pas été mis à jour vers les versions compromises — la protection a fonctionné. Mais l'incident a révélé que sans audit automatisé, on n'aurait jamais su.

Les leçons sont claires. Les virtualenvs isolés sont essentiels — sans eux, la mise à jour automatique aurait installé le malware. L'audit quotidien des versions compromises de packages Python est indispensable. Et surtout, la chaîne d'approvisionnement logicielle est désormais un champ de bataille actif. Ce n'est plus de la théorie de sécurité, c'est une réalité opérationnelle. TeamPCP n'est pas le dernier groupe à essayer cette approche. Le prochain scanner de sécurité compromis pourrait être celui que tu utilises.


Podcast: 🎙️ Episode MP3 (~11 min)