
21 октября 2026 года на PyPI и Docker Hub появился вредоносный LiteLLM 1.107.0: атакующие украли токены GitHub и выпустили релиз через штатный конвейер с подписью. За три часа пакет, по оценке, скачали более 49 000 раз. Внутри были стилер и RAT, которые охотятся за облачными ключами и ключами ИИ-сервисов — то есть ровно за тем, что хранит LLM-прокси.
Коротко
- Вредоносная версия — LiteLLM 1.107.0 на PyPI и Docker Hub, 21 октября 2026 года, окно около трёх часов, по оценке более 49 000 загрузок.
- Атакующие украли токены GitHub CLI из логов выставленного в интернет внутреннего инстанса, сняли branch protection и выпустили подписанный релиз из двойника Berri-AI/litellm.
- Нагрузка — стилер и RAT. Они запускаются при каждом старте Python и забирают облачные, ИИ-, SSH- и GPG-ключи.
- По данным Wiz, украденные ключи AWS через 4,5 часа использовали для запросов к Amazon Bedrock (LLMjacking).
- Чистая версия — 1.106.2. Откат не удаляет закрепление: нужны изоляция, ротация с чистой машины и пересборка среды.
Что выложили при взломе LiteLLM 1.107.0
Вредоносная версия одна — LiteLLM 1.107.0. Её опубликовали 21 октября 2026 года сразу в двух каналах: на PyPI и на Docker Hub. LiteLLM — открытый прокси, через который приложения обращаются к разным LLM-провайдерам по единому API. Его ставят и на ноутбуки разработчиков, и в продовые кластеры как шлюз к моделям.
Вредоносные пакеты оставались доступны около трёх часов. В источнике это окно указано общим, без разбивки по PyPI и Docker Hub. За это время их, по оценке, скачали более 49 000 раз. В среднем выходит больше 16 000 загрузок в час — около 270 в минуту.
Эту цифру надо читать аккуратно: она считает загрузки, а не заражённые организации. CI-конвейеры, зеркала и повторные сборки качают один и тот же пакет десятки раз. Но верно и обратное. Каждая автоматическая сборка без закреплённой версии в этом окне подтянула 1.107.0 сама, без участия человека.
Когда атаку обнаружили, версию сняли с PyPI. На Docker Hub заражённые теги и варианты образов удалили или переключили на чистые артефакты. Последний чистый релиз, который называет проект, — 1.106.2.
По заявлению LiteLLM, атака не задела корпоративных клиентов, которые получают пакет из приватного репозитория компании. Это слова самого проекта: как именно проверяли этот канал, публично не расписано.
23 октября инцидент подробно описал SecurityWeek. Технические детали добавили исследователи Wiz и StepSecurity.
Откуда у атакующих взялись токены GitHub CLI?
Атакующие нашли OAuth-токены GitHub CLI во внутреннем инстансе LiteLLM, выставленном в интернет. По данным расследования проекта, токены принадлежали «неожиданной, безобидно названной учётной записи» в этом развёртывании (в оригинале — an unexpected, innocuously named user account).
Как токены туда попали, LiteLLM объясняет гипотезой, а не установленным фактом. По версии мейнтейнеров, Claude Code «в определённых обстоятельствах» вкладывал токены в тело ответа, и такой ответ мог записаться в логи LiteLLM. Какие именно обстоятельства имелись в виду, проект не уточняет.
Прокси стоит между клиентом и моделью и при включённом логировании сохраняет запросы и ответы целиком. Допустим, ассистент разработчика выводит содержимое конфигурации или результат команды, где фигурирует токен. Тогда этот текст оседает в логах прокси — рядом с ключами провайдеров и промптами.
Дальше сработало простое свойство OAuth-токена GitHub CLI: это секрет предъявителя. Кто держит токен, тот действует от имени учётной записи в пределах её прав. Так доступ к логам прокси превратился в доступ к репозиториям и настройкам CI/CD.
В итоге у атакующих оказалось три комплекта учётных данных GitHub CLI, принадлежавших разработчикам. Как злоумышленники попали на выставленный инстанс и как переходили от одного комплекта к другому, проект пока до конца не выяснил.
Отдельный вопрос — сама «безобидно названная» учётная запись. Аккаунт, о котором не знали владельцы, во внутренней системе, открытой наружу, — классическая находка внешнего пентеста. Здесь она обошлась в подписанный релиз.
Практический урок для всех, кто держит у себя LLM-прокси: логи запросов и ответов — такое же хранилище секретов, как vault, только без его защиты. Маскирование токенов и ключей при записи, короткий срок хранения и узкий круг доступа нужны с первого дня, а не после инцидента.
Как из токена получился подписанный релиз
Атакующие захватили не файл в реестре, а сам процесс выпуска, поэтому релиз и вышел подписанным. По описанию LiteLLM, цепочка выглядела так:
- с украденными учётными данными сняли защиту веток (branch protection);
- влили изменение, которое перенаправило механизм выпуска (releaser) на другой исходный репозиторий;
- запустили скомпрометированный GitHub workflow, который брал код уже из репозитория-двойника;
- подписали отравленные артефакты и опубликовали их на PyPI и Docker Hub.
Двойник назывался Berri-AI/litellm, настоящий репозиторий — BerriAI/litellm. Разница в одном дефисе. В длинном YAML-файле конвейера её легко пропустить на ревью. Тем более что ревью никто не требовал: защиту веток только что сняли.
Обратите внимание: ни один шаг не потребовал уязвимости в коде LiteLLM или в самом PyPI. Хватило прав трёх разработчиков и того, что изменения в настройках выпуска не проходили через второй, независимый контур контроля.
Отсюда главный вывод для тех, кто полагается на подписи и «официальный источник». Подпись подтверждает, что артефакт выпустил определённый процесс или определённый ключ. О содержимом она ничего не говорит. Если атакующий управляет release workflow, вредоносный пакет подписывается тем же механизмом, что и все предыдущие, и проверка у потребителя пройдёт.
LiteLLM также считает, что вредоносный код, скорее всего, писали с помощью ИИ. Публичный разбор не приводит технических доказательств, так что это мнение пострадавшей стороны, не более.
Сценарий не новый: доверенное имя проекта не спасает, если скомпрометирован сам конвейер. О том, как реестры пакетов превращаются в канал доставки, мы писали и в разборе кампании PhantomRaven в npm.
Что стилер делает на машине с Python
Пакет ставит сразу два инструмента. Стилер разово выгребает секреты, а RAT оставляет атакующему постоянный доступ. Заражены все, кто установил 1.107.0 в окно публикации.
Механизм закрепления простой и неприятный. Полезная нагрузка кладёт три файла в корень site-packages, и они выполняются при каждом старте интерпретатора Python, а не только когда приложение импортирует litellm. Имена и тип файлов в публичных материалах не названы.
Похожий приём хорошо известен: при стандартной инициализации модуль site обрабатывает файлы .pth в site-packages и исполняет строки, начинающиеся с import. Использован ли здесь именно он, источники не уточняют. Итог один: любой вызов python, pip, pytest или entrypoint контейнера снова запускает вредоносный код.
Список того, что собирает стилер, похож на опись рабочей станции ML-инженера:
- сведения о системе;
- сохранённые пароли и cookie браузеров, то есть живые сессии;
- учётные данные инструментов разработчика и переменные окружения;
- секреты AWS, GCP и Azure;
- API-ключи ИИ-сервисов: Anthropic, OpenAI, GitHub Copilot и других;
- приватные SSH-ключи, ключи GPG и история командной оболочки.
Собранное шифруется и уходит на домен, который имитирует имя проекта. Не путайте его с репозиторием Berri-AI/litellm: репозиторий-двойник раздавал вредоносный код, домен-двойник принимает украденное. Адрес мы не приводим — индикаторы компрометации опубликовали LiteLLM и SecurityWeek, брать их нужно оттуда.
По данным StepSecurity, RAT регулярно выходит на сервер управления. Запасной канал у него на GitHub: раз в час он проверяет тайник (dead drop) в GitHub и, по формулировке компании, «выполняет любой Python, который подсунет атакующий». Трафик к GitHub в сети разработчиков — привычный фон, его почти никто не фильтрует. Поэтому блокировка основного сервера управление не обрывает.
Для LLM-прокси такой набор особенно болезнен. LiteLLM по своей роли хранит ключи ко всем провайдерам моделей, которыми пользуется компания, и часто работает с облачными ролями. Стилеру достаётся не случайный ноутбук, а место, где все ключи собраны вместе.
Почему через 4,5 часа это уже был LLMjacking
По наблюдениям Wiz, украденные ключи начали использовать примерно через 4,5 часа после выгрузки. Среди зафиксированных действий — запросы к моделям Amazon Bedrock с похищенными учётными данными AWS. Это типичная картина LLMjacking.
LLMjacking — это обращение к LLM-сервисам в чужом облачном аккаунте с украденными учётными данными. Атакующий получает бесплатные вычисления или перепродаёт доступ, а счёт за токены приходит владельцу аккаунта. Деньги уходят сразу, и первый сигнал скорее появится в биллинге, чем в DLP.
4,5 часа — короче рабочего дня. Если команда узнала о проблеме из новостей на следующее утро, ключи к этому моменту уже работали на атакующих. Если есть подозрение на 1.107.0, проверяйте не только логи доступа, но и потребление Bedrock и аналогичных сервисов в Azure и GCP.
В AWS начните с CloudTrail: вызовы InvokeModel с незнакомых адресов и в регионах, где вы Bedrock не используете, а также запросы на включение доступа к новым моделям. Бюджетные оповещения на ИИ-сервисы стоит настроить заранее — они срабатывают быстрее, чем кто-то откроет счёт в конце месяца.
Что делать, если LiteLLM 1.107.0 могли поставить?
Исходите из того, что любая система, где стоял 1.107.0, скомпрометирована целиком, а не просто «содержит плохой пакет». Откат на 1.106.2 нужен, но сам по себе ничего не лечит: файлы в site-packages переживают pip uninstall.
Мы рекомендуем такой порядок:
- Найти, где была версия. Проверьте lock-файлы, requirements без закреплённых версий, логи CI за 21 октября, внутренние зеркала PyPI, хранилища артефактов, кэши pip и собранные образы. Удаление из PyPI не удаляет пакет из ваших кэшей и зеркал, поэтому период риска длиннее трёхчасового окна.
- Проверить Docker по digest, а не по тегу. Тег можно переназначить. После переключения на чистый артефакт повторный docker pull скачает чистый образ и ничего не скажет о том, что работало 21 октября. Ищите sha256 в логах реестра, оркестратора и среды выполнения.
- Изолировать и сохранить. Отключите подозрительные хосты и CI-раннеры от сети, снимите образ диска или хотя бы каталог site-packages и логи установок. Не запускайте python, pip и тесты «для диагностики»: это снова активирует нагрузку. Осматривайте копию файловой системы.
- Ротировать с чистой машины и только после сдерживания. Пока RAT жив, новые секреты уйдут вслед за старыми. Порядок: облачные ключи и временные сессии AWS/GCP/Azure, токены GitHub, ключи LLM-провайдеров, SSH и GPG, браузерные сессии.
- Найти следы и пересобрать среду. Ищите нештатные файлы в корне site-packages, обращения к домену-двойнику из IOC проекта, периодические запросы процессов Python к GitHub, нетипичные вызовы Bedrock. Затем пересоберите среду из проверенных источников, а не «чистите» существующую.
Отдельно проверьте свою организацию на GitHub. В журнале аудита ищите отключение branch protection, правки файлов workflow и изменение источников выпуска. Отзовите OAuth-авторизации GitHub CLI у всех, кто работал с заражёнными машинами, и пересмотрите, у кого вообще есть право снимать защиту веток.
Клиентов, которые берут LiteLLM из приватного enterprise-репозитория, атака, по словам проекта, обошла. Но разработчики часто держат рядом открытую версию для локальных экспериментов, так что ноутбуки проверить всё равно нужно.
Из практики. На проектах по аудиту безопасности ML/AI мы раз за разом видим одну картину. LLM-прокси развёрнут «временно». Ради отладки запросы и ответы логируются целиком. Логи лежат там, куда есть доступ у половины команды, а сам инстанс выставлен в интернет, чтобы до него дотягивались внешние агенты.
В таких логах находятся ключи провайдеров, внутренние документы из промптов, иногда токены — ровно то, что случилось у LiteLLM. Проверьте, что пишут ваши прокси, кто читает логи и видна ли админка из интернета.
Закрепляйте версии и хэши зависимостей, требуйте ревью изменений workflow и не давайте одному токену снимать branch protection. Это базовая гигиена DevSecOps, и она рвёт описанную цепочку сразу в двух звеньях.
Если признаки заражения подтвердились, начинайте с реагирования на инцидент, а не с ротации наугад.
Что пока неизвестно и с чем не путать
Часть открытых вопросов прямо влияет на оценку риска:
- как атакующие попали на выставленный инстанс и как переходили между тремя комплектами учётных данных — проект сам называет это неясным;
- при каких именно обстоятельствах Claude Code вкладывал токены в ответ — пока это гипотеза LiteLLM без технических подробностей;
- сколько организаций реально заражено — оценка в 49 000 загрузок на этот вопрос не отвечает;
- кто атакует — группа, страна или псевдоним не названы;
- на чём основана оценка, что вредонос писали с помощью ИИ.
Одно можно сказать уже сейчас. ИИ-инструменты разработчика здесь оказались вероятным источником утечки, ИИ-прокси — целью, а облачные LLM — способом монетизации. Модель угроз для AI-инфраструктуры должна учитывать все три роли.
И ещё одно: этот эпизод не связан с историей о компрометации примерно 2500 организаций. У SecurityWeek есть отдельный материал о том, что за ней стоял Trivy, а не LiteLLM. Атака 21 октября самостоятельна: другая точка входа, конкретная версия 1.107.0, конкретное окно. Не смешивайте их в отчётах и тикетах — меры реагирования разные.
Частые вопросы
Какая версия LiteLLM вредоносная и какая безопасная?
Вредоносная — 1.107.0, опубликованная 21 октября 2026 года на PyPI и Docker Hub. Последняя чистая версия, которую называет проект, — 1.106.2.
Сколько времени вредоносный LiteLLM был на PyPI?
Около трёх часов; источник называет это окно общим для PyPI и Docker Hub. За это время пакет и образы скачали, по оценке, более 49 000 раз.
Что ворует вредоносный LiteLLM 1.107.0?
Сведения о системе, пароли и cookie браузеров, переменные окружения, секреты AWS, GCP и Azure, API-ключи Anthropic, OpenAI, GitHub Copilot и других сервисов, SSH- и GPG-ключи, историю командной оболочки. Кроме того, ставится RAT с удалённым выполнением Python.
Достаточно ли удалить LiteLLM 1.107.0, если он уже установлен?
Нет. Нагрузка кладёт три файла в site-packages и запускается при каждом старте Python. Систему нужно изолировать, ротировать все доступные ей секреты с чистой машины и пересобрать среду.
Затронул ли взлом корпоративных клиентов LiteLLM?
Проект утверждает, что нет: тех, кто получает пакет из приватного репозитория LiteLLM, атака не коснулась. Как это проверяли, компания не уточняла, поэтому локальные установки открытой версии у разработчиков стоит проверить отдельно.
Что такое LLMjacking?
Это использование украденных облачных учётных данных для обращения к LLM-сервисам в чужом аккаунте, например к Amazon Bedrock. Платит за это владелец аккаунта.
LLM-прокси, агенты и RAG давно хранят больше ключей, чем любой другой сервис в инфраструктуре. Команда SecurityLab.pro проверит, что они логируют, что видно снаружи и как защищён ваш конвейер выпуска, — при пентесте ИИ и LLM-приложений.