LiteLLM 1.107.0: в официальный релиз встроили стилер и бэкдор
PrimeCoder · 2026 · формат: news
Что произошло, почему это важно и что взять в работу.
Чистый код в GitHub не гарантирует чистый пакет — командам пора фиксировать версии и хеши, ставить карантинное зеркало PyPI и убирать долгоживущие ключи из CI.
Связанные услуги: каталог, AI Boost Team, стать клиентом.
Худший релиз в году для ИИ-инфраструктуры выглядел буднично: тег, подпись, статус официального пакета. Всё на месте. Внутри, по разбору УЦСБ, ехали инфостилер privcollect и бэкдор с удалённым выполнением кода. LiteLLM 1.107.0 несколько часов работал как единый API не только к моделям, но и к секретам того, кто его запустил.
Масштаб ставок понятен из двух чисел: около 90 млн скачиваний в месяц и больше 60 тыс. звёзд на GitHub. Это не нишевая библиотека, которую обновляют по пятницам. Это слой, через который приложение ходит к моделям разных провайдеров, а значит, сидит рядом с ключами и деньгами.
Что произошло и в какие часы
21 октября 2026 года конвейер публикации был скомпрометирован. Заражённые артефакты лежали в трёх местах с разными окнами экспозиции: в PyPI с 14:39 до 16:23 МСК, в Docker Hub с 14:46 до 17:20, в GHCR с 14:46 до 16:51. Затронуты все семь wheel-пакетов, а также образы litellm, litellm-database и litellm-non_root. Теги v1.107.0, latest, main-latest и main-stable указывали на заражённое.
Отдельно стоит запомнить оговорку про приватный реестр: он не затронут, enterprise-клиенты, которые тянут пакеты оттуда, инцидент не задели. Это важный сигнал для тех, кто выбирает схему поставки. Разница между «пакет из интернета» и «пакет из своего контура» здесь отработала как страховка.
Сборку увели в репозиторий с одним лишним дефисом
Код в официальном репозитории не менялся. Тег v1.107.0 там чистый. Атакующие вмешались в процесс публикации и перенаправили сборку в похожий репозиторий Berri-AI/litellm, который отличается от настоящего BerriAI/litellm одним дефисом. Пакет собрали, подписали и выпустили через штатный конвейер.
Вредоносный пакет собрали и подписали, не трогая официальный код. То есть чистый код на GitHub еще не гарантирует чистый пакет.
Входная точка появилась задолго до релиза. Мастер-ключ LiteLLM Agent Platform утёк в публичный репозиторий LiteLLM-Labs/lite-harness 27 мая 2026 года. Коммит с конфигурационным файлом переписали, а ключ не отозвали. 10 октября его использовали: получили GitHub CLI OAuth-токен владельца организации, затем токены двух мейнтейнеров, обошли защиту ветки. Проект к тому моменту временно ослабил процедуру согласования релизов. Этим и воспользовались.
Читается как учебник по тому, чего не делать с секретами в CI. Переписанная история коммита не отзывает ключ. Токен, который никто не сжёг, живёт до момента, когда им воспользуются, и никто не узнает, что он «светился».
Почему это срабатывает даже там, где есть сканеры
В пакеты добавили три файла: cook.pth, cook.py и sitecustomize.py. Они используют штатные механизмы запуска Python. cook.pth импортировал cook.py, который поднимал стилер privcollect. sitecustomize.py работал на Linux и macOS и запускал фоновый загрузчик для удалённого выполнения кода.
Дальше главное: вредонос активировался при любом запуске Python в заражённом окружении, включая запуск pip. То есть даже проверка «а какая версия у нас стоит» через pip show могла стоить ключей. Загрузчик раз в час обращался к GitHub-репозиторию letters9813/pythonclient-test, читал domain.txt с адресом управляющего сервера и скачивал скрипт с /codepy. Никакой экзотики, всё на инфраструктуре, которой разработчики доверяют по умолчанию.
Что уходит на сторону и что с этим делают
Стилер собирал облачные ключи AWS, Azure и Google Cloud, доступы к Kubernetes и Docker, токены GitHub, npm и PyPI, SSH-, GPG- и TLS-ключи, файлы .env, данные браузеров и токены AI-инструментов, включая Cursor и GitHub Copilot. Отправка шла на litellm.dev/healthcheck. Через 4,5 часа после утечки ключи AWS уже проверяли через sts:GetCallerIdentity, а затем смотрели модели Bedrock. Похоже на LLMjacking: чужой бюджет тратится на ваши счета за токены.
| Факт | Что это значит |
|---|---|
| Официальный релиз, подпись на месте | Подпись подтверждает, кто собрал пакет, а не что внутри. Проверять надо конвейер, а не только артефакт |
| Сборка ушла в Berri-AI/litellm | Опечатка в имени репозитория опаснее уязвимости: код чистый, а пакет нет |
| Активация при любом старте Python | Карантин «на посмотреть» не работает. Запуск pip в заражённом окружении уже утечка |
| Ключ утёк 27 мая, не отозван, применён 10 октября | Пять месяцев тишины между утечкой и атакой. Ротация секретов важнее их сложности |
| Внутренние зеркала и кеши | Заражённая версия продолжает жить в контуре после того, как её удалили из PyPI |
Это второй заход за год, и он другой
24 марта 2026 года в PyPI уже выходили вредоносные 1.82.7 и 1.82.8. Тогда полезная нагрузка сидела в proxy_server.py и срабатывала при импорте, а в 1.82.8 появился litellm_init.pth с запуском при каждом старте Python. Пакеты были доступны от 40 минут до 2,5 часов: LiteLLM говорил примерно о 40 минутах, PyPI о 2 часах 32 минутах. Данные уходили на models.litellm.cloud, а вредонос пытался закрепиться в Kubernetes через привилегированные поды. Чистой тогда считалась 1.82.6, чистая 1.83.0 вышла 30 марта. Инцидент связывают с группировкой TeamPCP и скомпрометированным GitHub Action aquasecurity/trivy-action, но связь подтверждена не полностью.
Разница между мартом и октябрём принципиальная. В марте правили код пакета, и это ловилось глазами при разборе. В октябре не тронули ни строчки кода, а переписали процедуру выпуска. Порог входа ниже: нужен не доступ к репозиторию, а один живой токен мейнтейнера.
Что делать, если 1.107.0 у вас запускалась
- Проверить следы: pip show litellm, lock-файлы, SBOM, локальные кеши, внутренние зеркала, образы и дайджесты, CI-раннеры и машины разработчиков.
- Не запускать Python и pip в этом окружении. Удалить cook.pth, cook.py, sitecustomize.py и связанные файлы __pycache__, остановить процесс, держащий /tmp/remote_code_loader.lock, пересобрать окружение или образ с нуля на версии 1.106.2.
- Считать данные скомпрометированными, если был исходящий интернет. С чистого хоста отозвать облачные ключи и роли, секреты Kubernetes и Docker, токены GitHub, npm и PyPI, SSH-, GPG- и TLS-ключи, .env, ключи провайдеров ИИ, master и virtual keys LiteLLM, пароль DATABASE_URL.
- Поискать маркеры: обращения к litellm.dev и letters9813/pythonclient-test, пути /codepy, переменную PRIVCOLLECT_ACTIVE=1, процесс с рабочим каталогом /. Вычистить затронутые артефакты из зеркал, реестров и кешей.
Вердикт
Покупать «безопасный open source» по звёздам на GitHub больше нельзя. Три правила, которые дешевле любого инцидента: фиксируйте LiteLLM и зависимости на конкретных версиях и хешах, не тяните latest в прод. Держите внутреннее зеркало с карантином, проверяйте подписи, provenance и SBOM. Уберите долгоживущие облачные ключи из CI и раннеров, замените короткоживущими токенами с минимальными правами, включите сканирование секретов с автоотзывом и фильтрацию исходящего трафика.
И самое неприятное. Чистый код в официальном репозитории теперь ничего не доказывает. Доказывает только воспроизводимая сборка, которую вы контролируете сами.