Компрометация LiteLLM: заражённые wheel-пакеты похищали секреты
Версия LiteLLM 1.107.0 содержала вредоносные загрузчики. Атакующие подменили сборку и могли получить доступ к ключам, токенам и секретам CI/CD.
21 октября разработчики библиотеки LiteLLM сообщили о компрометации версии 1.107.0. Все семь wheel-пакетов этого релиза содержали инструменты для кражи секретов и загрузки удалённого кода. Для запуска вредоносной части было достаточно запустить Python в окружении с установленным пакетом — даже если само приложение не импортировало и не использовало LiteLLM.

Заражённая версия находилась в PyPI с 11:39 до 13:23 UTC. Пострадали также образы в Docker Hub и GitHub Container Registry. При этом официальный Git-тег 1.107.0 оставался чистым: вредоносные артефакты создал и подписал штатный процесс сборки.
Как атакующие подменили сборку
По предварительной версии команды LiteLLM, злоумышленник получил GitHub CLI-токены из логов внутреннего сервиса, доступного из интернета. Токен с правами владельца организации позволил отключить защиту ветки и изменить направление сборки. Вместо репозитория BerriAI/litellm процесс начал использовать подставной Berri-AI/litellm.
В конфигурации сборщика maturin появилась строка data = "cook". Она добавляла каталог с вредоносными файлами в служебный раздел wheel. После установки содержимое переносилось в корень site-packages, где находятся модули Python. В исходном архиве каталога cook/ не было: вредоносный код присутствовал только в собранных wheel-артефактах.
Запуск через служебные файлы Python
Первой точкой запуска служил файл cook.pth со строкой import cook. Файлы с расширением .pth обычно используются для добавления путей поиска модулей, однако строки с командами import выполняются при инициализации Python. Поэтому проверка того, импортирует ли приложение LiteLLM, не позволяла определить, запускался ли вредоносный код.
Вторым механизмом был файл sitecustomize.py — Python автоматически загружает такой модуль при настройке окружения. Он запускал фоновый процесс, который раз в час получал адрес управляющего сервера из файла на GitHub, повторял сбор секретов и загружал код для исполнения.
Вредоносная программа искала SSH-ключи, облачные токены, секреты CI/CD и ключи ИИ-инструментов. Если у процесса был доступ к базе данных прокси LiteLLM, он также мог похитить ключи провайдеров языковых моделей.
Почему удаления пакета недостаточно
Удаление LiteLLM не останавливает уже запущенный фоновый процесс и не отзывает ключи, которые успели отправить атакующим. Поэтому после изоляции заражённой среды необходимо остановить подозрительные процессы, пересоздать окружения и отозвать все секреты, к которым мог быть доступ.
Аналогичный способ автоматического запуска вредоносного кода уже встречался в других кампаниях. По данным базы CodeScoring, пакет openai-mcp 2.41.1 использовал .pth-файл для загрузки среды исполнения JavaScript Bun и запуска JS-кода. В пакете claudedashbord 0.1.0 загрузка удалённого кода через такой хук была отложена на 12 часов. Однако в случае LiteLLM механизм оказался встроен в официальный релиз, а заражённые пакеты собрал и подписал легитимный CI-процесс.
Что проверить пользователям
Разработчики рекомендуют закрепить версию LiteLLM 1.106.2. При расследовании нужно сверить версии в метаданных установок и кэшах, а контейнеры проверить по digest, указанным в отчёте об инциденте. Также важно установить, запускался ли Python в заражённом окружении.
Начинать проверку с команды pip show рискованно: при определённых условиях сам pip запускает интерпретатор Python. Кроме того, отсутствие файлов закладки после очистки не доказывает, что среда оставалась безопасной — вредоносный процесс мог уже запуститься, а секреты могли быть похищены ранее.
Инцидент показывает, что доверие к названию библиотеки, корректной подписи и чистому Git-тегу не заменяет проверку содержимого конечного артефакта. В CodeScoring версия LiteLLM 1.107.0 отмечена как вредоносная. Пользователи CodeScoring могут выявлять её при анализе состава зависимостей и блокировать загрузку с помощью CodeScoring.OSA и политики «Зависимость опасна».
Сообщить о проблеме в публикации
Обращение принято Обращение будет рассмотрено. По результатам проверки публикация может быть исправлена, дополнена, временно скрыта или удалена.