Tinycolor supply chain attack post-mortem
Атака на поставки @ctrl/tinycolor: разбор инцидента
Злоумышленник добавил вредоносный workflow в GitHub Actions общего репозитория и похитил npm-токен с правами публикации. С помощью этого токена были опубликованы вредоносные версии 20 пакетов, включая @ctrl/tinycolor.
Мой аккаунт GitHub и репозиторий @ctrl/tinycolor не были скомпрометированы напрямую. Не использовался фишинг, на моём компьютере не устанавливались вредоносные пакеты. GitHub и npm оперативно отреагировали, удалив зловредные версии. Я выпустил чистые версии пакетов для очистки кэшей.
Как это произошло
Раньше я участвовал в проекте angulartics2 — общем репозитории, где у нескольких человек были права администратора. Там остался секрет GitHub Actions — npm-токен с широкими правами на публикацию.
Злоумышленник принудительно отправил ветку Shai-Hulud в angulartics2 с вредоносным workflow. Workflow запустился сразу после отправки (без проверки, так как у collaborator были права администратора) и украл npm-токен. С помощью украденного токена атакующий опубликовал вредоносные версии 20 пакетов.
Планы на будущее
Сейчас я использую semantic-release с GitHub Actions для публикации. Моя цель — перейти на Trusted Publishing (OIDC) в npm, чтобы полностью отказаться от статических токенов. Однако интеграция с semantic-release ещё в разработке.
Для небольших пакетов я продолжу использовать semantic-release, но с ужесточённым контролем: никаких новых участников, отдельные npm-токены с правами только на публикацию конкретного пакета.
Я планирую и дальше использовать pnpm, который блокирует неавторизованные postinstall-скрипты, и изучу новую настройку minimumReleaseAge.
Пожелания к системе публикации
В идеале хотелось бы иметь в npm единый переключатель для принудительного использования Trusted Publishing (OIDC) для всех моих пакетов. Такой же переключатель блокировал бы любые релизы без provenance, обеспечивая безопасность на уровне аккаунта. Также хотелось бы иметь встроенную поддержку semantic-release с OIDC и provenance, чтобы статические токены больше не требовались.
Кроме того, было бы удобно иметь безопасный вариант публикации с подтверждением человека прямо в интерфейсе GitHub: защищённый workflow_dispatch, использующий 2FA GitHub для удовлетворения требованиям двухфакторной аутентификации без необходимости публиковать со своего компьютера.