LiteLLM, la passerelle open source qu'utilisent de nombreuses équipes pour aiguiller leurs requêtes vers des dizaines de fournisseurs de modèles de langage, a publié le 21 octobre une version malveillante. La 1.107.0 a été mise en ligne sur PyPI et poussée vers les images du projet sur Docker Hub et GitHub Container Registry après la prise de contrôle de son processus de publication, selon un rapport d'incident signé par le dirigeant, le directeur technique et le responsable sécurité de l'entreprise. LiteLLM affirme que l'incident est maîtrisé et que toutes les versions antérieures sont sûres.
La fenêtre d'exposition a été brève mais large. Les sept paquets wheel de la 1.107.0 étaient téléchargeables sur PyPI entre 11 h 39 et 13 h 23 UTC. Sur Docker Hub, les étiquettes v1.107.0, latest, main-latest et main-stable ont renvoyé vers une image compromise de 11 h 46 à 14 h 20 UTC, tandis que leurs équivalentes sur GHCR étaient retirées à 13 h 51. Datadog Security Labs, qui crédite LiteLLM d'environ 23 millions de téléchargements par semaine, prévient que toute installation sans version figée ou tout recours à ces étiquettes mobiles pendant cet intervalle peut être touché. Les clients du registre privé réservé aux entreprises ont été épargnés.
La charge malveillante était conçue pour s'exécuter sans même que LiteLLM soit importé. Chaque paquet déposait dans site-packages un fichier cook.pth, un programme espion cook.py et un script sitecustomize.py, si bien que le code se lançait à chaque démarrage de Python. D'après la fiche OSV des paquets malveillants et l'analyse de Datadog, le programme récoltait clés cloud et métadonnées d'instances, clés SSH et GPG, secrets Kubernetes, Vault et d'intégration continue, données de navigateur et dossiers de configuration d'outils de programmation dopés à l'IA, puis les chiffrait avant de les envoyer vers un domaine trompeur, litellm[.]dev. Le second script interrogeait toutes les heures une adresse distante pour télécharger et exécuter du code. Selon Datadog, ce fichier de commande n'a jamais contenu que des valeurs de test : aucune seconde phase n'a été observée.
Le récit de LiteLLM sur le déroulé de l'attaque reste provisoire. L'entreprise indique que l'attaquant détenait les jetons GitHub CLI de trois développeurs. L'un d'eux, appartenant à un propriétaire de l'organisation, a permis de forcer la protection des branches du processus privé de publication et de le rediriger vers Berri-AI/litellm, une copie dont le nom ne diffère du véritable BerriAI/litellm que par un tiret. Un deuxième jeton a franchi l'étape d'approbation en production, un troisième a ensuite effacé les traces de l'opération. L'étiquette officielle du code source 1.107.0 n'a jamais contenu les fichiers malveillants.
La provenance des jetons constitue le point le plus embarrassant. LiteLLM dit avoir découvert un compte utilisateur inattendu sur une instance interne de LiteLLM exposée sur internet et pense que l'attaquant a lu les jetons dans les journaux de cette instance. L'entreprise ajoute que Claude Code peut, dans certaines situations, insérer le jeton OAuth GitHub CLI d'un utilisateur dans le corps d'une réponse, lequel se retrouve dans les journaux quand les réponses sont enregistrées. La manière dont l'intrus a pénétré cette instance n'est pas confirmée ; LiteLLM soupçonne une vulnérabilité corrigée récemment.
C'est la deuxième fois cette année que LiteLLM sert de vecteur à un logiciel malveillant. En mars, les versions 1.82.7 et 1.82.8 avaient été compromises lors d'une campagne que Datadog attribue à un groupe baptisé TeamPCP ; OX Security relève que les outils et l'infrastructure diffèrent cette fois et aucun lien n'a été établi. L'affaire montre qu'une passerelle d'IA, qui concentre par construction toutes les clés de fournisseurs d'une organisation, devient une cible de premier choix.
Les recommandations de LiteLLM et des spécialistes de la sécurité sont sans détour. Quiconque a installé la 1.107.0 ou lancé une image touchée doit considérer la machine comme compromise, supprimer les fichiers déposés avant de relancer Python, reconstruire ses environnements en figeant la version 1.106.2 et renouveler tous les identifiants accessibles, y compris les clés de fournisseurs stockées dans la base du proxy. LiteLLM précise que l'enquête et la chronologie continuent d'être mises à jour.