Атака на GitHub: как автоматизированные PR с ИИ-помощью угрожают цепочкам поставок

information security

В начале апреля 2026 года кибербезопасность сообщества разработчиков с открытым исходным кодом столкнулась с новой реальностью: масштабной автоматизированной атакой, использующей возможности искусственного интеллекта для эксплуатации известных уязвимостей в системах непрерывной интеграции. Хотя публично активность была задокументирована 2 апреля, расследование показывает, что кампания началась значительно раньше и демонстрирует тревожную эволюцию тактик злоумышленников.

Описание

Факты и хронология инцидента

Исследователь Чарли Эриксен сообщил об автоматизированной кампании, эксплуатирующей триггер "pull_request_target" в GitHub Actions. Злоумышленник под аккаунтом "ezmtebo" создал более 475 вредоносных запросов на слияние (pull request, PR) за 26 часов, целясь в репозитории как крупных организаций, так и отдельных разработчиков. Однако, как выяснилось, это была лишь видимая часть айсберга.

Специалисты Wiz Research идентифицировали в общей сложности шесть волн активности одного и того же угрозового актора, стартовавших ещё 11 марта - за три недели до публичного раскрытия. На протяжении всех волн злоумышленник создал более 500 вредоносных PR, успешно скомпрометировал как минимум два пакета в реестре npm и эволюционировал от примитивных bash-скриптов до сложных, сгенерированных ИИ полезных нагрузок, адаптированных под язык программирования целевого проекта. При этом, несмотря на сложную многоэтапную конструкцию, атака демонстрирует фундаментальное непонимание модели угроз GitHub, что существенно ограничило её успех.

Механика эксплуатации: старая уязвимость, новый масштаб

В основе кампании лежит давно документированная, но по-прежнему распространённая ошибка конфигурации - некорректное использование триггера "pull_request_target" в GitHub Actions. В отличие от стандартного триггера "pull_request", "pull_request_target" выполняется в контексте базового репозитория, а не форка. Это означает, что если рабочий процесс (workflow) настроен без должных ограничений, код из непроверенного внешнего PR получает доступ к секретам (secrets) основного репозитория, таким как токены API, ключи облачных провайдеров и другие учётные данные.

Сценарий атаки был отточен до автоматизма: поиск репозиториев, использующих уязвимый триггер; создание форка; внедрение вредоносной полезной нагрузки в файл, который выполняется в процессе CI/CD (например, "conftest.py", "package.json", "Makefile", "build.rs"); открытие PR с безобидным названием вроде "ci: update build configuration". В случае успешного запуска вредоносного рабочего процесса происходила кража токена "GITHUB_TOKEN", перечисление других секретов, зондирование метаданных облачных сервисов (AWS, Azure, GCP) и их утечка через закодированные в base64 маркеры в логах или комментарии к PR. При обнаружении "NPM_TOKEN" злоумышленник публиковал вредоносную версию пакета.

Эволюция от зондирования до ИИ-масштабирования

Анализ шести волн показывает чёткий прогресс в методах и инструментах атакующего. Первые волны в середине марта ("testedbefore", "beforetested-boop") характеризовались сырыми подходами с прямым внедрением shell-скриптов. После двухнедельной паузы в конце марта активность возобновилась с аккаунтами "420tb" и "69tf420". Полезная нагрузка в этой фазе представляла собой прямой 351-строчный bash-скрипт ("prt_exfil.sh"), размещаемый в директории ".github".

Наиболее показательной стала финальная фаза в начале апреля с аккаунтами "elzotebo" и публично раскрытым "ezmtebo". Здесь проявился качественный скачок: атакующий начал использовать сгенерированные ИИ, адаптивные обёртки для полезной нагрузки. Вместо универсального скрипта система анализировала стек технологий целевого репозитория и создавала идиоматичный код: Go-тесты для проектов на Go, npm-скрипты для JavaScript, файлы "conftest.py" для Python. Это позволило увеличить скорость до 7 PR в час и вести атаку на протяжении более 22 часов почти без остановки, целясь в том числе в репозитории высокого профиля.

Амбициозный дизайн против неуклюжего исполнения

Несмотря на внешнюю сложность, анализ полезной нагрузки выявляет серьёзный разрыв между амбициями и технической грамотностью. Каждая полезная нагрузка следовала одной пятифазной структуре: EXFIL (утечка переменных окружения), RECON (разведка), DISPATCH (создание временного workflow), LABEL_BYPASS (попытка обхода проверок через метки) и DELAYED (фоновое сканирование). Однако ключевые фазы, такие как DISPATCH и LABEL_BYPASS, были обречены на провал, так как для их выполнения требуются права на запись в репозиторий, которые по умолчанию отсутствуют у токена в контексте "pull_request_target".

Атакующий демонстрирует автоматизацию, но не глубокое понимание платформы. Попытки доступа к сервису метаданных инстансов (IMDS) на GitHub-hosted раннерах заведомо бесполезны и лишь повышают заметность. Частыми были ошибки в сопоставлении, когда, например, в репозиторий на Python внедрялся payload для "build.rs" (специфичный для Rust). Это указывает на низкий уровень технической осведомлённости самого оператора, который, однако, компенсируется мощными автоматизированными инструментами.

Последствия и успешность: низкий процент, но реальные компрометации

Общий уровень успеха кампании оценивается менее чем в 10%. Крупные проекты, включая Sentry, OpenSearch, IPFS и другие, успешно отразили атаки благодаря настройкам обязательного одобрения PR от новых контрибьюторов (first-time contributor approval gates) и другим практикам безопасности CI/CD. Это обнадёживающий сигнал для сообщества: базовые меры защиты работают.

Однако даже при низком проценте успеха 500 попыток дают десятки компрометаций. Наиболее серьёзным подтверждённым последствием стало compromise двух пакетов npm ("@codfish/eslint-config" и "@codfish/actions"), в которые были опубликованы вредоносные версии. Также зафиксированы случаи кражи AWS-ключей, токенов Cloudflare и Netlify. Атака наглядно показывает, что автоматизация позволяет даже малоопытному злоумышленнику методом "тыка" достигать целей в цепочке поставок.

Новый ландшафт угроз: скорость ИИ против человеческого контроля

Данная кампания знаменует собой важный сдвиг. Использование ИИ-агентов для анализа репозиториев, динамической генерации кода и массового создания PR снижает порог входа для проведения сложных атак на цепочки поставок. То, что раньше требовало экспертизы и ручной работы, теперь может выполняться на машинной скорости. Хотя текущая реализация была неуклюжей, она демонстрирует вектор развития. Каждая следующая волна была сложнее предыдущей: улучшалась маскировка, повышалась осведомлённость о стеке технологий, усиливалась операционная безопасность.

Это вызов для всего сообщества открытого исходного кода. Защита теперь должна учитывать не только технические уязвимости вроде "pull_request_target", но и скорость, с которой они могут быть просканированы и использованы. Приоритетом для организаций должен стать аудит конфигураций GitHub Actions, безусловное требование ручного одобрения для первого PR от нового контрибьютора и регулярный мониторинг активности в репозиториях на предмет аномальных паттернов. В новой реальности автоматизированные атаки становятся нормой, и защита должна успевать за их темпом.

Индикаторы компрометации

GitHub Accounts

  • testedbefore <testedbefore@proton.me>
  • beforetested-boop <testedbefore+89@proton.me>
  • 420tb <testedbefore+55@proton.me>
  • 69tf420 <testedbefore+99@proton.me>
  • elzotebo <elzotebo@proton.me>
  • ezmtebo <elzotebo+88@proton.me>

Malicious Branch Pattern

  • prt-scan-[12-character-hex]

PR Signatures

  • Title: 'ci: update build configuration'
  • Body: 'Automated build configuration update.'
  • User-Agent: python-requests/2.32.5
Комментарии: 0