Руководства по безопасности
Цепочка компрометаций TanStack, Nx Console и GitHub (май 2026): что проверить разработчикам
В мае 2026 года компрометация TanStack в npm привела к подменённому расширению Nx Console для VS Code и краже внутренних репозиториев GitHub. По трём официальным разборам: как проверить, затронуты ли вы, какие учётные данные сменить и какие настройки CI пересмотреть.
Для кого эта статья: для разработчиков, которые устанавливают зависимости JavaScript через npm (включая pnpm и yarn), для всех, кто пользуется расширениями в VS Code или его форках, для мейнтейнеров, публикующих пакеты из GitHub Actions, и для администраторов GitHub Enterprise Server. Статья основана на разборах и сообщениях, опубликованных TanStack, Nx и GitHub, и не описывает техники атаки.
Что сделать разработчикам сегодня
Проверьте lock-файлы и журналы CI на затронутые версии TanStack
Затронуты 42 пакета Router/Start, 84 версии, включая @tanstack/react-router, @tanstack/react-start, @tanstack/router-core и @tanstack/history (полный список — в бюллетене GitHub GHSA-g7cv-rxg3-hmpx). TanStack говорит, что Query, Table, Form, Virtual и другие её пакеты затронуты не были. Проверяйте не только текущее содержимое lock-файла, но и историю его изменений около 11 мая 2026 года. Вредоносные версии удалили из npm за несколько часов, поэтому установка в это окно может не отражаться в сегодняшнем lock-файле. В CI ищите задания, которые выполняли установку после 19:20 UTC 11 мая.
Проверьте, была ли у вас Nx Console v18.95.0
В разборе Nx показано, как проверить установленную версию командой code --list-extensions --show-versions (ID расширения содержит angular-console). Затронута только v18.95.0, и она была доступна 18 мая с 12:30 до 13:09 UTC. Nx просит всех, у кого в это окно была Nx Console с включённым автообновлением, считать машину скомпрометированной — какая бы из цифр установок ни оказалась верной. В разборе также перечислены файлы и процессы, которые нужно искать (индикаторы компрометации); если вы затронуты, пройдите по этому списку.
Если затронуты, смените все учётные данные, доступные с этой машины
TanStack и Nx перечисляют одни и те же цели: токены GitHub, токены npm, ключи SSH, учётные данные облаков (AWS, GCP, Azure), Kubernetes, токены Vault и содержимое любых файлов .env. Nx добавляет учётные данные, которые инструменты на машине могли выпустить в это окно (временные учётные данные облаков, токены GitHub CLI и т. д.), и рекомендует после смены рассмотреть полную переустановку машины. О порядке отзыва и о том, что делать с закрепившимся вредоносным ПО, см. раздел «если есть подозрение на заражение» в статье защита от червей в цепочке поставок npm.
Если вы мейнтейнер пакетов npm, проверьте историю публикаций
По словам TanStack, код искал другие пакеты, которые поддерживает жертва, и пытался переопубликовать их с тем же внедрением. Если вы публикуете в npm, проверьте историю версий своих пакетов на версии, которые вы не публиковали, начиная с 11 мая.
Выясните, где на вашей машине хранится токен GitHub
По словам Nx, украденным учётным данным был токен GitHub CLI. В той среде он хранился в файле на диске и был доступен для чтения любому процессу, запущенному от имени пользователя, и был использован против API GitHub в течение 74 секунд. Выполните gh auth status, чтобы увидеть, где хранится ваш; если он лежит в обычном файле, подумайте о переносе в связку ключей ОС или в интеграцию с менеджером паролей, которая подставляет учётные данные только во время запуска. После инцидента политика Nx запрещает прямое использование GitHub CLI на машинах разработчиков. О сокращении срока жизни и прав токенов см. защиту от червей в цепочке поставок npm.
Проверьте, что настройка возраста релиза действительно действует
По словам Nx, в проекте скомпрометированного участника в .npmrc было указано minimum-release-age=10080 (7 дней), но проект закреплял pnpm 10.14, которая не поддерживает эту настройку и молча её игнорировала. Поддержка появилась в pnpm 10.16. На момент установки вредоносной версии было всего 77 минут, так что работающая настройка её бы заблокировала. Проверьте версию, закреплённую в поле packageManager файла package.json, и пусть CI проверяет, что она достаточно новая. Аналогичная настройка для npm описана в статье защита от червей в цепочке поставок npm.
Администраторам GitHub Enterprise Server: смените ключ подписи
26 мая GitHub объявил, что меняет ключи, включая ключ, которым подписываются пакеты обновлений GitHub Enterprise Server. Администраторы должны сменить открытые ключи GPG в своём экземпляре; иначе будущие обновления завершатся ошибкой о том, что файл не является корректным пакетом GHES. Инструкции и дайджест SHA256 вспомогательного скрипта приведены в публикации GitHub. GitHub также просит скачивать обновления GHES только из официального источника и готовиться в ближайшие месяцы устанавливать обновления безопасности чаще. Клиентам GitHub Enterprise Cloud ничего делать не нужно.
Что пересмотреть в CI тем, кто публикует пакеты
В разборах TanStack и Nx прямо сказано, какие настройки пропустили цепочку. Ниже эти выводы переведены в настройки и правила, которые можно проверить в своих репозиториях.
Не запускайте код форков под pull_request_target
По словам TanStack, workflow для проверки размера бандла запускался на pull_request_target и внутри него получал и собирал код из pull request форка. pull_request_target выполняется с правами основного репозитория, и TanStack отмечает, что проверка одобрения для новых участников не применяется к этому триггеру. Оставьте его для задач, которые никогда не запускают чужой код, — например, расстановки меток и комментариев. После инцидента TanStack убрала из своего CI все использования pull_request_target.
Не делите кэш между недоверенными заданиями и заданиями релиза
По словам TanStack, кэш GitHub Actions общий на уровне репозитория: запуски pull_request_target и push в main используют одну и ту же область. Сохранение в кэш также не блокируется, если задать permissions: workflow только на чтение. В результате workflow релиза восстановил кэш, записанный заданием, которое выполняло чужой код. После инцидента TanStack отключила кэш пакетов в пайплайне релиза и очистила все кэши. Не восстанавливать кэш в workflow, которые публикуют, — самая простая граница.
Давайте право публикации (id-token: write) только заданию публикации и только после одобрения
У workflow релиза TanStack было id-token: write для доверенной публикации в npm (OIDC). Согласно разбору, вредоносная публикация произошла не на шаге публикации, определённом в workflow: код, выполнявшийся на другом этапе того же запуска, извлёк токен и опубликовал пакеты напрямую. Собственный вывод TanStack: у привязки доверенного издателя нет проверки каждой публикации. Выделите публикацию в отдельное задание, отдельно от сборки и тестов, дайте право только ему и поставьте его за окружение GitHub с обязательными рецензентами. После инцидента Nx сделала обязательным для публикации одобрение человеком, отличным от того, кто запустил процесс.
Закрепляйте сторонние actions по SHA коммита
После инцидента и TanStack, и Nx закрепили все ссылки на actions по SHA коммита вместо тега или ветки. TanStack называет подвижные ссылки «постоянным риском для цепочки поставок, не зависящим от этого инцидента».
Направляйте уведомления о публикации и журналы аудита тому, кто их читает
Nx обнаружила подменённый релиз благодаря обычному письму, которое магазин расширений отправляет при каждой загрузке. Мейнтейнер, не ожидавший релиза, понял, что это аномалия, и снял публикацию примерно за 11 минут. Во втором канале распространения такого уведомления не было, и удаление там заняло около 36 минут. Тем временем действия с украденным токеном, например удаление запусков workflow, неделю лежали в журнале аудита незамеченными. Проверьте, что уведомления о публикации доходят до кого-то в команде и что кто-то следит за удалением запусков workflow в журнале аудита.
Что произошло (по сообщениям трёх организаций)
Всё ниже изложено так, как сказано в разборе TanStack, разборе Nx и сообщении GitHub. Время — UTC.
11 мая 2026, 19:20–19:26
Через workflow релиза репозитория Router/Start проекта TanStack в npm публикуются 84 вредоносные версии в 42 пакетах.11 мая, 19:46
Внешний исследователь оставляет подробный отчёт в репозитории TanStack. TanStack начинает реагирование.11 мая, 20:43
Участник Nx запускаетpnpm installв проекте, не связанном с Nx, и получает вредоносный@tanstack/zod-adapter@1.166.15. По словам Nx, токен GitHub CLI был украден и использован в течение 74 секунд.11 мая, к 21:03
TanStack помечает все 84 версии как устаревшие (deprecated).11 мая, 22:13–23:55
npm удаляет затронутые архивы пакетов из реестра.15 мая
TanStack объявляет отбой тревоги: все опубликованные сейчас версии безопасны.18 мая, 12:30–13:09
С помощью украденного доступа участника в двух каналах распространения расширений публикуется, а затем снимается Nx Console v18.95.0.18 мая (понедельник, по времени США)
GitHub обнаруживает и сдерживает компрометацию устройства сотрудника, связанную с заражённым расширением VS Code, удаляет вредоносную версию расширения и изолирует устройство. Критичные секреты меняются в тот же и на следующий день.20 мая
GitHub сообщает публично: по его оценке, наружу выведены только внутренние репозитории GitHub.21 мая
Nx публикует свой разбор.26 мая
GitHub обновляет публикацию: меняет ключи, включая ключ подписи GitHub Enterprise Server, и перечисляет действия для администраторов.
- TanStack: масштаб
- 42 пакета, 84 версии из репозитория Router/Start. Query, DB, Store, Table, Form, Virtual и другие репозитории не затронуты. TanStack говорит, что у неё нет свидетельств кражи токенов npm
- TanStack: что делал код
- Выполнялся как скрипт при установке, собирал учётные данные облаков, Kubernetes, Vault, npm, GitHub и SSH и отправлял их наружу, а также пытался распространиться на другие пакеты, которые поддерживает жертва
- TanStack: первопричина
- Сочетание (1) сборки кода форков под
pull_request_target, (2) возможности этого задания записать кэш, который восстанавливает workflow релиза, и (3) возможности workflow релиза получить токен OIDC с правом публикации - Nx: масштаб
- Только Nx Console v18.95.0 (v18.100.0 и более поздние безопасны). Nx CLI, официальные плагины
@nx/*и Nx Cloud не затронуты. Официальный магазин насчитал 28 установок, второй канал — 41 загрузку. Собственная аналитика Nx показывает около 6 000 активаций, и расхождение ещё выясняется - Nx: первопричина
- (1) Компрометация TanStack выше по цепочке, (2) настройка возраста релиза, которую старая pnpm молча игнорировала, (3) токен GitHub CLI, доступный для чтения на диске, (4) пайплайн, позволявший одному участнику опубликовать расширение
- GitHub: масштаб
- Оценка: вывод наружу только внутренних репозиториев GitHub. Нет свидетельств воздействия на информацию клиентов, хранящуюся вне их, например на собственные предприятия, организации и репозитории клиентов. В некоторых внутренних репозиториях всё же есть информация клиентов, например фрагменты обращений в поддержку
- GitHub: ответ
- Удалил вредоносную версию расширения и изолировал устройство. Сменил критичные секреты, начиная с самых значимых. Сменил ключи, включая ключ подписи GitHub Enterprise Server, и попросил администраторов сменить открытый ключ. Говорит, что опубликует более полный отчёт, когда расследование завершится
Как это читать: «число репозиториев, взятых из GitHub», — не цифра самого GitHub
В публикации GitHub упоминается число выведенных наружу репозиториев, но эту цифру компания приводит как заявление атакующего и говорит лишь, что она «в целом согласуется» с её расследованием на данный момент. Этот сайт не считает заявления атакующих фактами, поэтому цифра здесь не повторяется. Так же Nx говорит, что её данные об установках расходятся между источниками и ещё сверяются. Решайте не по цифрам, а по тому, была ли у вас затронутая версия в это окно.
Где можно было разорвать цепочку
1. CI проекта TanStack
Код чужого PR пишет в кэш, общий с релизом
↓→
Разорвать здесь
Без pull_request_target / без восстановления кэша в workflow публикации / одобрение для публикации
2. 84 вредоносные версии npm
Опубликованы легитимным путём, поэтому выглядели настоящими
↓→
Разорвать здесь
Задержка по возрасту релиза — в версии инструмента, которая её соблюдает
3. Машина участника Nx
Токен GitHub CLI прочитан из файла на диске
↓→
Разорвать здесь
Никаких файлов с токенами открытым текстом / следить за удалениями в журнале аудита
4. Nx Console v18.95.0
Доступа одного человека хватает для публикации расширения
↓→
Разорвать здесь
Требовать одобрения от человека, отличного от запустившего
5. Устройство сотрудника GitHub
Заражённое расширение, затем вывод внутренних репозиториев
↓→
Разорвать здесь
Относиться к обновлениям расширений как к зависимостям (следующий раздел)
Что на этот раз не доказало безопасность
- Легитимный путь публикации и provenance: вредоносные версии TanStack вышли через действующую привязку OIDC
- Аккаунт реального участника: Nx Console была опубликована с настоящим доступом участника
- Автоматические проверки канала распространения: по словам Nx, подменённая версия прошла автоматическую проверку официального магазина
- Настройки, которые были заданы, но фактически не применялись: настройку возраста релиза старая pnpm молча игнорировала
Что могло разорвать цепочку (по разборам)
- Одобрение второго человека перед публикацией: в других репозиториях у Nx оно уже было, но не в Nx Console
- Отделение workflow публикации от кэша: TanStack отключила кэш после инцидента
- Задержка по возрасту релиза, которая действительно работает: на момент установки вредоносной версии было 77 минут
- Человек, читающий обычное уведомление о публикации: это был единственный способ, которым Nx обнаружила проблему
Взгляд этого сайта: автообновление расширений — это автоматический приём зависимостей
Для зависимостей npm правило «не устанавливать ничего, опубликованного за последние несколько дней» становится обычной практикой. Расширения редактора же обычно обновляются автоматически по умолчанию, и тот же подход до них ещё не дошёл. Поэтому Nx и написала, что всем, у кого было включено автообновление, следует исходить из компрометации. А расширение работает на машине, где хранятся ваши учётные данные GitHub и облака, и с вашими правами. На машинах с правами на продакшен или на публикацию пакетов подумайте о том, чтобы отключить автоматические обновления настройкой VS Code extensions.autoUpdate и устанавливать обновления самостоятельно через несколько дней. Цена — более медленные исправления безопасности, но версию, которую сняли через несколько минут после выхода, как здесь, обходит одна лишь задержка.
И ещё одно: эта цепочка пересекла границы организаций. Участник Nx установил вредоносный пакет в проекте, не связанном с Nx, а сотрудник GitHub установил расширение Nx. Ваша машина разработчика — часть цепочки поставок каждого проекта, в который вы отправляете код, а не только проекта вашего работодателя.
Источники (открытые данные)
Факты в этой статье взяты из открытых источников ниже. Техники атаки и сведения, позволяющие установить атакующих, не приводятся.
- TanStack, «Postmortem: TanStack npm supply-chain compromise» (опубликовано 11 мая 2026 года; обновлено 15 мая) — tanstack.com
- TanStack, «Hardening TanStack After the npm Compromise» (изменения после инцидента) — tanstack.com
- GitHub Advisory Database, «GHSA-g7cv-rxg3-hmpx (CVE-2026-45321)» (полный список затронутых версий) — github.com
- Nx, «Postmortem: Nx Console v18.95.0 supply-chain compromise» (21 мая 2026 года) — nx.dev
- Бюллетень безопасности Nx Console «GHSA-c9j4-9m59-847w» — github.com
- GitHub, «Investigation update: GitHub Enterprise Server signing key rotation» (опубликовано 20 мая 2026 года; обновлено 26 мая) — github.blog
- GitHub Security Lab, «Keeping your GitHub Actions and workflows secure: Preventing pwn requests» (безопасное использование pull_request_target) — securitylab.github.com
- GitHub Docs, «Managing environments for deployment» (обязательные рецензенты) — docs.github.com
История обновлений
2026-09-30: Первая версия на основе разбора TanStack (редакция от 15 мая), разбора Nx (21 мая) и сообщения GitHub (обновление от 26 мая). GitHub говорит, что опубликует более полный отчёт, когда расследование завершится; тогда мы обновим эту страницу.
Читать дальше
- Та же схема и порядок отзыва: защита от червей в цепочке поставок npm
- Не допускайте секретов в репозитории: останавливаем секреты при коммите с gitleaks / чем опасны .env и API-ключи
- Утечки через действительные учётные данные: в 2026 году утечки шли через действительные учётные данные (на английском)
- Защита аккаунтов: как выбрать многофакторную аутентификацию / минимальные привилегии для SSH-ключей
- Другие инциденты 2026 года: утечки данных и кибератаки 2026 года / утечка данных Canvas (Instructure) (на английском)
FAQ
QКакие пакеты TanStack были скомпрометированы?
Согласно разбору TanStack, затронуты 42 пакета, публикуемых из репозитория Router/Start, по две версии каждого, всего 84 версии (например, @tanstack/react-router 1.169.5 и 1.169.8, @tanstack/history 1.161.9 и 1.161.12). Полный список — в бюллетене безопасности GitHub GHSA-g7cv-rxg3-hmpx (CVE-2026-45321). Пакеты из других репозиториев, таких как Query, Table, Form и Virtual, затронуты не были, и TanStack говорит, что все опубликованные сейчас версии безопасны для установки.
QЧто делать, если я установил затронутую версию?
TanStack настоятельно рекомендует всем, кто установил затронутую версию 11 мая 2026 года (UTC), сменить учётные данные AWS, GCP, Kubernetes, Vault, GitHub, npm и SSH, доступные с машины, где шла установка. Поскольку код выполнялся при установке, в счёт идут не только машины разработчиков, но и раннеры CI.
QЯ использую Nx Console. Меня это затронуло?
Согласно разбору Nx, затронута только Nx Console v18.95.0, и она была доступна 18 мая 2026 года с 12:30 до 13:09 UTC. v18.100.0 и более поздние безопасны. Nx просит всех, у кого в это окно была установлена Nx Console с включённым автообновлением, считать машину скомпрометированной и сменить все учётные данные. Nx CLI (пакет nx), официальные плагины @nx/* и Nx Cloud затронуты не были.
QУтекли ли репозитории пользователей GitHub?
По словам GitHub, речь идёт о выводе наружу только внутренних репозиториев GitHub, и у компании нет свидетельств воздействия на информацию клиентов, хранящуюся вне этих репозиториев, например на собственные предприятия, организации и репозитории клиентов. В некоторых внутренних репозиториях всё же есть информация клиентов, например фрагменты обращений в поддержку, и GitHub говорит, что уведомит клиентов по установленным каналам, если воздействие будет обнаружено. Клиентам GitHub Enterprise Cloud ничего делать не нужно.
QЧто нужно сделать администраторам GitHub Enterprise Server?
В обновлении от 26 мая GitHub сообщил, что меняет ключи, включая ключ, которым подписываются пакеты обновлений GitHub Enterprise Server, и попросил администраторов сменить открытые ключи GPG в своих экземплярах. Без этой смены будущие обновления не пройдут проверку. Инструкции и дайджест SHA256 вспомогательного скрипта приведены в публикации GitHub. GitHub также просит скачивать обновления GHES только из официального источника.
QСвязаны ли эти три инцидента?
Связь TanStack и Nx указана в разборе Nx: 11 мая участник Nx запустил pnpm install в постороннем проекте, получил скомпрометированный @tanstack/zod-adapter 1.166.15, и у него украли токен GitHub CLI. В публикации GitHub «заражённое расширение VS Code», скомпрометировавшее устройство сотрудника, связано ссылкой с бюллетенем безопасности Nx Console.
QКакова была первопричина?
В разборе TanStack названы три слабых места, которые сработали только вместе: workflow на pull_request_target собирал код из pull request форков; это задание могло записывать в кэш GitHub Actions, общий с workflow релиза; а workflow релиза мог получить токен OIDC (короткоживущий токен, который выдаётся на каждый запуск CI), используемый для публикации в npm. Nx называет настройку возраста релиза, которую старая версия pnpm молча игнорировала, токен, хранившийся там, где его мог прочитать любой локальный процесс, и пайплайн, позволявший одному человеку опубликовать расширение.