Рабочие процессы GitHub Actions, которые считывали хранимые в репозитории секреты и отправляли их на внешний сервис, выполнялись в репозитории BerriAI/litellm более чем за неделю до атаки на релизный конвейер. Эта атака 21 октября 2026 года привела к публикации вредоносных пакетов litellm версии 1.107.0 в PyPI и вредоносного образа контейнера. Наблюдения показывают, что доступ к организации GitHub появился задолго до этого дня, а следы запусков почти не отразились в обычной истории репозитория.
Описание
Восстановлены два коммита, каждый из которых добавлял рабочий процесс с именем cache.yml под одним и тем же заголовком, имитирующим правку настроек кэша. Первый датирован 10 октября 2026 года, 22:11 по UTC, второй - 12 октября. Как установили в Socket, обе операции проводились в короткоживущих ветках со случайным набором символов в имени, которые создавались, использовались и удалялись в течение минут. Метрики производительности GitHub Actions при этом фиксируют по одному успешному запуску для каждого из двух коммитов.
Запись в метриках подтверждает, что рабочий процесс с этим именем существовал и выполнялся 10 октября: в ней указаны один запуск, одна задача, средняя длительность четыре секунды и ноль процентов отказов по задачам. Такие значения согласуются с устройством восстановленного файла, который не выгружает содержимое репозитория и не выполняет сборку. Второй, более долговечный след оставили записи о развёртываниях в средах: привязка задачи к среде создаёт запись, которая остаётся видимой и после удаления файла рабочего процесса. Пять имён сред, к которым привязывались задачи второго запуска, присутствуют в перечне сред репозитория, то есть перечень изучили до написания файла.
Первый файл занимал 24 строки и описывал одну задачу: он считывал шесть секретов уровня организации, записывал их построчно в файл, кодировал результат в одну строку и отправлял запросом на внешний сервис. Ошибки отправки подавлялись, поэтому задача завершалась успешно независимо от результата запроса. Второй файл занимал 97 строк и повторял ту же операцию шесть раз, причём пять задач привязывались к средам, чтобы открыть доступ к секретам этих сред. Наборы секретов в двух запусках не пересекаются, а получатели различались одноразовыми идентификаторами, что согласуется с разведкой, после которой последовал более широкий сбор.
В двух файлах упомянуты 20 различных имён секретов. В первом запуске собраны шесть: токен GitHub, идентификатор и закрытый ключ приложения GitHub App, ключ доступа к рабочему пространству Linear, ключ развёрнутого LiteLLM и ключ платного сервиса Together AI. Токен и ключ приложения относятся к платформе, которая размещает репозиторий, а не к стороннему сервису; ключ приложения подписывает токены установки и не истекает так, как пользовательский токен. Во втором запуске собраны 14 других секретов, среди них ключи платных модельных API, ключ доступа к сервису сканирования секретов GitGuardian, строка подключения к PostgreSQL с паролем, пароль Redis и сериализованное состояние браузерной сессии Linear, дающее доступ к аккаунту без пароля и второго фактора.
Для запуска такого рабочего процесса нужны права на отправку в сам репозиторий: GitHub не раскрывает секреты репозитория и сред рабочим процессам, запущенным из форков по запросам на слияние. Журнал активности связывает все шесть операций, то есть создание двух веток, две отправки и два удаления, с одной учётной записью участника организации. Оба коммита не подписаны, а поля автора и коммиттера участник с правами отправки может заполнить произвольно. Журнал показывает, какая учётная запись выполняла операцию, но не кто ею пользовался: украденная сессия и законный владелец оставляют одинаковую запись. По журналам аудита проекта токен, похищенный 10 октября, связан с одобрением вредоносного релиза 21 октября, а первоначальным доступом назван мастер-ключ платформы агентов, случайно попавший в публичный репозиторий в мае и не отозванный.
Последнее развёртывание в одной из сред помечено как активное, носит заголовок вредоносного коммита и выполнено из короткоживущей ветки; более ранние записи в той же среде относятся к тестовым развёртываниям марта. Сами по себе такие записи вредоносности не доказывают, как и метрики запусков: похожие следы оставляют обычные рабочие процессы и тестовые развёртывания. Не установлено, был ли октябрь началом активности, поскольку цикл из создания ветки, отправки, запуска и удаления оставляет мало следов. Неясно, сколько ещё циклов прошло между 12 и 21 октября: для полного подсчёта нужны вся история запусков и журнал активности, а не только метрики. Не установлено и как получен доступ к учётной записи: для этого нужны данные журнала аудита GitHub с адресами, клиентами и историей сессий, которых представление репозитория не содержит. Не подтверждено получение данных: подавление ошибок означает, что успешная задача не доказывает успешную передачу, а использование похищенных платформенных учётных данных не прослежено.