Атака на AI-инструмент gpt-pilot провалилась из-за форматтера кода ruff: злоумышленник украл аккаунт сооснователя, но не смог обойти CI

security

Начало июня 2026 года запомнится сообществу разработчиков как день, когда форматтер кода спас репозиторий с 33 700 звёздами от серьёзной утечки учётных данных. Восьмого июня злоумышленник получил контроль над аккаунтом сооснователя компании Pythagora и попытался внедрить вредоносную нагрузку в основную ветку популярного AI-средства разработки gpt-pilot. Эта программа, которую называют "первым настоящим AI-программистом", широко используется для построения workflow с автоматической генерацией кода. Попытка провалилась благодаря двум последовательным проверкам в непрерывной интеграции (CI) - сначала форматтер ruff отказался принимать неотформатированный файл, а затем линтер обнаружил нарушение правил импорта.

Описание

Инцидент начался с компрометации учётной записи LeonOstrez на GitHub. Как выяснилось позже, основной ветке репозитория не были настроены правила защиты веток. Это позволило злоумышленнику выполнить принудительную отправку (force push) прямо в main, минуя ревью кода. В первой попытке он заменил всю цепочку коммитов на поддельную, содержащую вредоносные файлы. Вместо чистого коммита, который просто откатывал изменения промокода, появился изменённый, добавляющий три файла в директорию core/telemetry/: _hooks.py, _runtime.bin и модифицированный __init__.py.

Однако сразу после первой отправки CI запустила проверку форматирования с помощью утилиты ruff. Она показала, что один файл не соответствует правилам: в _hooks.py на 59-й строке было многострочное обращение к subprocess.check_output, которое следовало уместить в одну строку. Все шесть заданий CI, разбитые по трём версиям Python и двум операционным системам, завершились ошибкой. Через двенадцать минут злоумышленник исправил форматирование и повторил push. Но на этот раз линтер обнаружил нарушение: в файле __init__.py на 399-й строке появился импорт модуля threading не в начале файла, а после определения класса Telemetry, что противоречит руководству PEP 8. Снова все проверки не прошли. После этого атакующий прекратил попытки, а сообщество сообщило о подозрительной активности через issue, которое, впрочем, было быстро удалено самим злоумышленником.

Вредоносная нагрузка, которую пытался внедрить злоумышленник, оказалась чрезвычайно сложной. Файл _runtime.bin размером 758 КБ на самом деле является обфусцированным JavaScript-стилером учётных данных, предназначенным для кражи ключей доступа к AWS, токенов npm, секретов GitHub, сервисных аккаунтов Kubernetes, токенов HashiCorp Vault и SSH-ключей. Вредоносное средство использует сообщения коммитов GitHub как скрытый канал управления (C2): оно ищет в публичных коммитах маркер "thebeautifulsnadsoftime" и извлекает закодированные команды. Украденные данные стилер сохраняет в виде новых репозиториев, создавая коммиты от имени подставного адреса. Кроме того, вредонос оснащён механизмами закрепления в системе: он прописывает себя в настройках инструментов Claude Code и VS Code, чтобы перезапускаться при каждом новом сеансе разработки.

Специалисты StepSecurity в своём отчёте связали этот инцидент с кампанией Shai-Hulud, которая ранее поразила репозитории компаний Microsoft, Red Hat и Mistral AI. Общие признаки включают одинаковый загрузчик Bun версии 1.3.13, схему именования файлов и использование того же маркера C2. Примечательно, что исходный код упрощённой версии этого вредоноса был опубликован публично 12 мая 2026 года, поэтому не исключено, что атаку совершили подражатели. Однако сложность пятиуровневой обфускации и злоупотребление инфраструктурой Sigstore (экосистемой для подписи артефактов) указывают на опытную группировку.

Этот случай наглядно демонстрирует, что даже в крупных проектах с открытым исходным кодом защитой может служить дисциплина форматирования кода. Форматтер ruff, предназначенный для поддержания единого стиля, неожиданно стал барьером на пути атаки. Если бы не строгие правила CI, вредоносная нагрузка попала бы в дистрибутив, и тысячи разработчиков, установивших gpt-pilot, могли лишиться доступа к своим облачным сервисам. История также напоминает о необходимости настройки защиты веток на GitHub и о том, что даже автоматические проверки стиля могут сыграть критическую роль в безопасности цепочки поставок.

Атаки на открытые репозитории становятся всё более изощрёнными. Злоумышленники не просто пытаются украсть исходный код, а стремятся получить доступ к учётным данным разработчиков, чтобы распространяться дальше по цепочке. В этом году кампания Shai-Hulud уже затронула такие гиганты, как Microsoft, Red Hat и Mistral AI. Инцидент с gpt-pilot мог стать пятым крупным инцидентом за двое суток, но благодаря банальному требованию к форматированию кода этого не произошло. Разработчикам стоит извлечь урок: инструменты, которые кажутся вспомогательными, на самом деле могут быть последней линией обороны.

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

MD5

  • 7090625f760b831d607c9a38cfc58c4b
  • a722b89f887f226672d0ee4f708794f8

SHA256

  • 51b4dd39a15af1e28e97adc375849d688423ec3d88e8010644395fcdea52a3cc
  • c96f37e1b9cdc9683a300909492ed9f770b620d0037e5b80e23753cba7ca4077

C2 Marker (GitHub commit search)

  • thebeautifulsnadsoftime

C2 Command Extraction Regex

  • thebeautifulsnadsoftime ([A-Za-z0-9+/=]{1,30})\.([A-Za-z0-9+/=]{1,700})

Exfiltration Identity

  • claude@users.noreply.github.com

Singleton Mutex

"Another instance is already running"

Daemonization Flag

  • __DAEMONIZED

Token Patterns

  • npm_[A-Za-z0-9]{36,}
  • ghp_[A-Za-z0-9]{36}
  • gho_[A-Za-z0-9]{36}
  • ghs_[A-Za-z0-9]{36,}
  • AKIA[0-9A-Z]{16}

Комментарии: 0