1500 npm-пакетов можно было угнать, просто заняв старое имя на GitHub

leer en español

5902
1500 npm-пакетов можно было угнать, просто заняв старое имя на GitHub

Обычное переименование репозитория превращало Trusted Publishing в окно для подмены релиза.

image

Защитный механизм npm оказался способен передать право на выпуск чужого пакета тому, кто просто занял освободившееся имя репозитория. Bloom Security обнаружила проблему SlugFest и насчитала более 1500 потенциально уязвимых пакетов с суммарно более чем 10 млн загрузок и свыше 1 млн загрузок в месяц. Для атаки не требовалось похищать учётные данные.

Trusted Publishing позволяет публиковать релизы из GitHub Actions без постоянного npm-токена. CI/CD получает короткоживущий OIDC-токен, который npm проверяет перед выдачей временных прав на публикацию. Ошибка скрывалась в привязке доверия: до первого успешного релиза npm сохранял текстовый адрес owner/repository, а не постоянные числовые идентификаторы репозитория и владельца.

Если разработчик переименовывал, переносил или удалял связанный репозиторий, старый адрес мог снова стать доступным. Атакующий мог зарегистрировать репозиторий с прежним именем, создать workflow с нужным названием и получить корректный OIDC-токен. npm видел совпавший адрес и выдавал временный токен публикации, хотя новый репозиторий уже принадлежал другому владельцу.

Bloom проверила схему на собственном npm-пакете и подконтрольных репозиториях. Исследователи смогли выпустить новую версию из репозитория другой организации, не похищая npm- или GitHub-учётные данные. Вредоносный релиз мог сохранить имя, репутацию и зависимости легитимного пакета, а postinstall-сценарий запускал бы код при установке. Реальные атаки через SlugFest не подтверждены.

Риск усиливает автоматизация разработки. По измерениям Bloom, обычная рабочая станция получает около 70 пакетов в месяц через ИИ-агентов, а машина разработчика около 350. Агент может выбрать свежую версию зависимости без ручной проверки происхождения. Похожую проблему уже показывали ИИ-зависимости, где автоматический выбор пакетов расширяет поверхность атаки.

GitHub получила отчёт 6 июня и подтвердила проблему 9 июня, а исправление появилось 2 октября. Компания изменила правила: непроверенная конфигурация Trusted Publishing теперь живёт только 48 часов, после чего теряет право публиковать. Первый успешный релиз подтверждает привязку к неизменяемой идентичности репозитория. npm также перестал принимать Trusted Publishing-токены из событий issue_comment.

Сопровождающим советуют проверить привязки через npm trust list, удалить настройки для переименованных, перенесённых или удалённых репозиториев и создать новые. После новой привязки лучше сразу выпустить релиз, чтобы npm зафиксировал постоянный идентификатор. Дополнительный барьер даёт поэтапная публикация, где выпуск требует одобрения сопровождающего с 2FA.