В середине июля 2026 года на реестр RubyGems.org было опубликовано несколько вредоносных версий трёх пакетов, которые исследователи назвали SleeperGem. Эта скоординированная атака на цепочку поставок затронула пакеты git_credential_manager, Dendreo и fastlane-plugin-run_tests_firebase_testlab. Каждый из них представлял собой загрузчик, который скачивал второй этап атаки с сервера, контролируемого злоумышленниками, проверял, запущен ли код в среде сборки, и при обнаружении такой среды ничего не делал. На машинах разработчиков загрузчик устанавливал собственный демон и закреплялся в системе, используя как минимум два механизма автозапуска. Инцидент затрагивает всех, кто использует RubyGems в своих проектах, особенно разработчиков, работающих на локальных машинах.
Описание
Основные факты атаки были установлены компанией StepSecurity, которая запускала каждый скомпрометированный пакет в контролируемой среде GitHub Actions с инструментом Harden-Runner в режиме аудита. Сравнение таймингов публикации новых версий на RubyGems с метками релизов в исходных репозиториях на GitHub подтвердило, что эти версии не прошли через обычный процесс разработки. Например, пакет Dendreo не обновлялся с 2020 года, но 18 июля 2026 года получил сразу две новые версии - 1.1.3 и 1.1.4. Пакет fastlane-plugin-run_tests_firebase_testlab получил версию 0.3.2 19 июля при том, что в репозитории на GitHub теги заканчивались на v0.3.1 от 2019 года. Пакет git_credential_manager выдавал себя за официальный Microsoft Git Credential Manager и имел четыре вредоносные версии: 2.8.0, 2.8.1, 2.8.2 и 2.8.3.
Механизм атаки построен так, чтобы оставаться незамеченным в конвейерах непрерывной интеграции. Первым действием загрузчик проверяет около тридцати переменных окружения, характерных для CI-платформ, включая GITHUB_ACTIONS, GITLAB_CI и CIRCLECI. При обнаружении любой из них исполнение немедленно прекращается. Это означает, что обычная установка пакета в среде CI не проявляет вредоносной активности, и обнаружить атаку можно только при анализе поведения на машине разработчика. Чтобы изучить реальную цепочку, исследователям пришлось удалить эти переменные перед запуском кода, имитируя окружение разработчика.
Каждая вредоносная версия содержит минимальную логику: сам пакет - это лишь загрузчик. Для git_credential_manager версии 2.8.2 и выше код запускается в момент подключения библиотеки (require), а не только при установке. При вызове require пакет порождает дочерний процесс Ruby, который выполняет встроенный скрипт установки. Этот скрипт скачивает два файла с командно-контрольного сервера - shell-скрипт deploy.sh и нативный бинарный файл, имя которого совпадает с названием имитируемого инструмента. Загрузка выполняется с помощью встроенного HTTP-клиента Ruby с отключённой проверкой сертификатов, а в заголовок User-Agent устанавливается слово Git, чтобы трафик смешивался с обычными Git-запросами. Командно-контрольный сервер размещён на публичном экземпляре Forgejo, и учётная запись злоумышленника зарегистрирована под именем, похожим на официальный аккаунт экосистемы Git.
Как показал анализ Harden-Runner, в версии 2.8.2 строки, запускающие скачанный скрипт, были закомментированы - она только скачивала полезную нагрузку, не выполняя её. Версия 2.8.3 уже снимает эту блокировку и запускает полную цепочку. На машине разработчика скрипт install копирует скачанный бинарный файл в скрытый каталог в домашней папке пользователя ($HOME/.local/share/gcm/), делает его исполняемым и запускает в фоне как демон. Затем он устанавливает закрепление двумя способами: как пользовательский сервис systemd и как задачу cron, обе с безобидным именем git-credential-manager. Если пользователь имеет возможность выполнять sudo без пароля, скрипт повторно запускается от root и устанавливает setuid-копию оболочки в /usr/local/sbin/ping6 с правами 6777. В тестовом окружении такой возможности не было, но код этой ветки присутствует и активен.
Для пакета fastlane-plugin-run_tests_firebase_testlab наблюдался доступ к тому же командно-контрольному серверу, что подтверждает координацию атаки: три инцидента являются частью одной кампании, а не разрозненными случаями. Сами пакеты не содержат кода кражи учётных данных - эта логика находится внутри нативного демона, который загрузчик устанавливает. Характеристики сетевой активности самого демона требуют отдельного анализа, но уже ясно, что его задача - эксфильтрация данных и боковое перемещение.
Компрометация разработческой машины означает, что все секреты, хранящиеся на ней (SSH-ключи, токены облачных провайдеров, переменные окружения, пароли в браузере), должны считаться скомпрометированными. Кроме того, злоумышленники могут получить доступ к системам, к которым машина имеет привилегии, в том числе к репозиториям кода и CI-инфраструктуре. Для реагирования StepSecurity рекомендует немедленно удалить демон из каталога ~/.local/share/gcm/, отключить systemd-сервис и cron-задание с именем git-credential-manager, проверить наличие setuid-файла /usr/local/sbin/ping6, и сменить все учётные данные, к которым мог быть доступ. Если в вашем окружении наблюдается исходящий трафик на git.disroot.org, это прямое свидетельство выполнения загрузчика.
Для защиты от подобных атак в будущем следует использовать инструменты, которые контролируют сетевые соединения в раннерах CI. Harden-Runner в режиме блокировки разрешает только явно указанные конечные точки, что не позволяет загрузчику обратиться к неожиданному хосту даже с виду легитимному. На машинах разработчиков нужно развернуть сканирование файлов на наличие известных артефактов: кода загрузчика, скрипта deploy.sh с упоминанием ping6, и записей автозапуска, указывающих на демон. Эти меры позволяют обнаружить атаку ещё до того, как злоумышленники смогут выполнить эксфильтрацию. Событие SleeperGem показывает, что атаки на цепочку поставок становятся всё более изощрёнными - они комбинируют имитацию популярных инструментов с обходом систем непрерывной интеграции и нацелены именно на локальные машины разработчиков, где защита обычно слабее.
Индикаторы компрометации
Package
- git_credential_manager 2.8.0, 2.8.1, 2.8.2, 2.8.3
- Dendreo 1.1.3, 1.1.4
- fastlane-plugin-run_tests_firebase_testlab 0.3.2