Ce qui se passe
La fiche du 22 octobre disait que l'attaquant avait probablement tiré des jetons
GitHub des journaux d'un déploiement interne. Le rapport de LiteLLM (Oliver
Jensen, Mateo Wang) écarte cette piste : l'origine est une clé maître
publiée par erreur le 27 mai 2026 dans le dépôt public
LiteLLM-Labs/lite-harness, au fichier harnesses/opencode/opencode.json
(commit e10b14a). Le commit a été écrasé de force, la clé était identifiée
comme à révoquer, mais la révocation n'a jamais eu lieu pour celle-là. LiteLLM
reconnaît que ses hypothèses ont changé au fil de l'enquête.
La chaîne d'attaque
Le 10 octobre, l'attaquant (adresse 69.48.229[.]143) se sert de la clé et
extrait de la plateforme un jeton OAuth du GitHub CLI, sans restriction de
périmètre et lié au compte du propriétaire de l'organisation : accès
propriétaire à tous les dépôts. Entre 22:11 et 22:12 UTC, il pousse sur des branches jetables des
dépôts BerriAI/litellm et BerriAI/litellm-auto un workflow
.github/workflows/cache.yml, sous le message ci: bump cache config. Il se
déclenche à chaque push et envoie les secrets vers des adresses
webhook[.]site, puis les branches sont supprimées.
Le 21 octobre, la publication se joue en une heure (UTC) :
- 10:08 à 11:08 : protection de branche contournée, pipeline de release
repointé vers le dépôt sosie
Berri-AI/litellm(avec un trait d'union) - 11:39 à 11:40 : 1.107.0 publiée sur PyPI ; 11:46 : images Docker Hub et GHCR
- 12:06 : alerte de Lidor Machluf (Upwind) ; 13:23 : PyPI met la version en quarantaine ; 14:20 : tags Docker nettoyés
Normalement, une release exige un ingénieur autorisé et l'approbation d'un compte verrouillé sur un appareil physique. Cette règle avait été assouplie plus tôt dans la semaine, pour accélérer les versions et les backports : deux ingénieurs quelconques pouvaient lancer et approuver. L'attaquant a utilisé un des deux jetons volés pour lancer, l'autre pour approuver.
Ce que les workflows volaient
Socket a retrouvé deux commits, du 10 octobre (22:11:45 UTC) et du 12, sur des
branches ci-tmp-a351cc et ci-tmp-4d8517 : créées, utilisées et supprimées en
quelques minutes, elles ne laissent presque rien dans l'historique ordinaire du
dépôt, d'où le recours au journal d'activité. La seconde exécution élargit la collecte aux clés Anthropic,
OpenAI, AWS Bedrock, Tavily et GitGuardian, à l'état de stockage Playwright
(accès à un compte Linear sans mot de passe ni MFA), aux accès PostgreSQL et
Redis. Les données partaient vers webhook[.]site/65a42464-3cfa-4b02-a18c-17a6d7b86f37
et webhook[.]site/4da03473-a3e7-4dc2-a087-9c564b4208e1.
Côté paquet, le voleur envoie ses données à litellm[.]dev/healthcheck, domaine
enregistré le 13 octobre. Microsoft précise que les fichiers de démarrage
vivent hors du dossier de LiteLLM : supprimer seulement l'application peut les
laisser en place. Les fichiers indicateurs sont dans la fiche du 22 octobre.
Comment s'y prendre
- Révoquer, pas réécrire. Une clé passée dans un dépôt public est compromise, quoi que dise l'historique. Rotation, puis vérification que la révocation a bien eu lieu : c'est ce pas qui a manqué.
- Restreindre les jetons d'automatisation : celui-ci donnait accès à toute l'organisation.
- Garder la double approbation d'une publication, et alerter sur toute modification de protection de branche.
- Chercher dans vos dépôts :
.github/workflows/cache.ymlrécent, messageci: bump cache config, branchesci-tmp-*dans le journal d'activité, trafic verslitellm[.]devetwebhook[.]site.
Source : The Hacker News, 24 octobre 2026. Source en anglais. Rapport de LiteLLM, analyse de Socket et de Microsoft.