Перейти к содержимому
>_ITDITDПлатформа веб-безопасности

Руководства по безопасности

Цепочка компрометаций TanStack, Nx Console и GitHub (май 2026): что проверить разработчикам

В мае 2026 года компрометация TanStack в npm привела к подменённому расширению Nx Console для VS Code и краже внутренних репозиториев GitHub. По трём официальным разборам: как проверить, затронуты ли вы, какие учётные данные сменить и какие настройки CI пересмотреть.

Опубликовано 2026-09-30 Обновлено 2026-09-30 Последняя проверка 2026-09-30 16 мин чтения

Для кого эта статья: для разработчиков, которые устанавливают зависимости JavaScript через npm (включая pnpm и yarn), для всех, кто пользуется расширениями в VS Code или его форках, для мейнтейнеров, публикующих пакеты из GitHub Actions, и для администраторов GitHub Enterprise Server. Статья основана на разборах и сообщениях, опубликованных TanStack, Nx и GitHub, и не описывает техники атаки.

Что сделать разработчикам сегодня

1

Проверьте 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 мая.

2

Проверьте, была ли у вас 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 с включённым автообновлением, считать машину скомпрометированной — какая бы из цифр установок ни оказалась верной. В разборе также перечислены файлы и процессы, которые нужно искать (индикаторы компрометации); если вы затронуты, пройдите по этому списку.

3

Если затронуты, смените все учётные данные, доступные с этой машины

TanStack и Nx перечисляют одни и те же цели: токены GitHub, токены npm, ключи SSH, учётные данные облаков (AWS, GCP, Azure), Kubernetes, токены Vault и содержимое любых файлов .env. Nx добавляет учётные данные, которые инструменты на машине могли выпустить в это окно (временные учётные данные облаков, токены GitHub CLI и т. д.), и рекомендует после смены рассмотреть полную переустановку машины. О порядке отзыва и о том, что делать с закрепившимся вредоносным ПО, см. раздел «если есть подозрение на заражение» в статье защита от червей в цепочке поставок npm.

4

Если вы мейнтейнер пакетов npm, проверьте историю публикаций

По словам TanStack, код искал другие пакеты, которые поддерживает жертва, и пытался переопубликовать их с тем же внедрением. Если вы публикуете в npm, проверьте историю версий своих пакетов на версии, которые вы не публиковали, начиная с 11 мая.

5

Выясните, где на вашей машине хранится токен GitHub

По словам Nx, украденным учётным данным был токен GitHub CLI. В той среде он хранился в файле на диске и был доступен для чтения любому процессу, запущенному от имени пользователя, и был использован против API GitHub в течение 74 секунд. Выполните gh auth status, чтобы увидеть, где хранится ваш; если он лежит в обычном файле, подумайте о переносе в связку ключей ОС или в интеграцию с менеджером паролей, которая подставляет учётные данные только во время запуска. После инцидента политика Nx запрещает прямое использование GitHub CLI на машинах разработчиков. О сокращении срока жизни и прав токенов см. защиту от червей в цепочке поставок npm.

6

Проверьте, что настройка возраста релиза действительно действует

По словам Nx, в проекте скомпрометированного участника в .npmrc было указано minimum-release-age=10080 (7 дней), но проект закреплял pnpm 10.14, которая не поддерживает эту настройку и молча её игнорировала. Поддержка появилась в pnpm 10.16. На момент установки вредоносной версии было всего 77 минут, так что работающая настройка её бы заблокировала. Проверьте версию, закреплённую в поле packageManager файла package.json, и пусть CI проверяет, что она достаточно новая. Аналогичная настройка для npm описана в статье защита от червей в цепочке поставок npm.

7

Администраторам GitHub Enterprise Server: смените ключ подписи

26 мая GitHub объявил, что меняет ключи, включая ключ, которым подписываются пакеты обновлений GitHub Enterprise Server. Администраторы должны сменить открытые ключи GPG в своём экземпляре; иначе будущие обновления завершатся ошибкой о том, что файл не является корректным пакетом GHES. Инструкции и дайджест SHA256 вспомогательного скрипта приведены в публикации GitHub. GitHub также просит скачивать обновления GHES только из официального источника и готовиться в ближайшие месяцы устанавливать обновления безопасности чаще. Клиентам GitHub Enterprise Cloud ничего делать не нужно.

Что пересмотреть в CI тем, кто публикует пакеты

В разборах TanStack и Nx прямо сказано, какие настройки пропустили цепочку. Ниже эти выводы переведены в настройки и правила, которые можно проверить в своих репозиториях.

1

Не запускайте код форков под pull_request_target

По словам TanStack, workflow для проверки размера бандла запускался на pull_request_target и внутри него получал и собирал код из pull request форка. pull_request_target выполняется с правами основного репозитория, и TanStack отмечает, что проверка одобрения для новых участников не применяется к этому триггеру. Оставьте его для задач, которые никогда не запускают чужой код, — например, расстановки меток и комментариев. После инцидента TanStack убрала из своего CI все использования pull_request_target.

2

Не делите кэш между недоверенными заданиями и заданиями релиза

По словам TanStack, кэш GitHub Actions общий на уровне репозитория: запуски pull_request_target и push в main используют одну и ту же область. Сохранение в кэш также не блокируется, если задать permissions: workflow только на чтение. В результате workflow релиза восстановил кэш, записанный заданием, которое выполняло чужой код. После инцидента TanStack отключила кэш пакетов в пайплайне релиза и очистила все кэши. Не восстанавливать кэш в workflow, которые публикуют, — самая простая граница.

3

Давайте право публикации (id-token: write) только заданию публикации и только после одобрения

У workflow релиза TanStack было id-token: write для доверенной публикации в npm (OIDC). Согласно разбору, вредоносная публикация произошла не на шаге публикации, определённом в workflow: код, выполнявшийся на другом этапе того же запуска, извлёк токен и опубликовал пакеты напрямую. Собственный вывод TanStack: у привязки доверенного издателя нет проверки каждой публикации. Выделите публикацию в отдельное задание, отдельно от сборки и тестов, дайте право только ему и поставьте его за окружение GitHub с обязательными рецензентами. После инцидента Nx сделала обязательным для публикации одобрение человеком, отличным от того, кто запустил процесс.

4

Закрепляйте сторонние actions по SHA коммита

После инцидента и TanStack, и Nx закрепили все ссылки на actions по SHA коммита вместо тега или ветки. TanStack называет подвижные ссылки «постоянным риском для цепочки поставок, не зависящим от этого инцидента».

5

Направляйте уведомления о публикации и журналы аудита тому, кто их читает

Nx обнаружила подменённый релиз благодаря обычному письму, которое магазин расширений отправляет при каждой загрузке. Мейнтейнер, не ожидавший релиза, понял, что это аномалия, и снял публикацию примерно за 11 минут. Во втором канале распространения такого уведомления не было, и удаление там заняло около 36 минут. Тем временем действия с украденным токеном, например удаление запусков workflow, неделю лежали в журнале аудита незамеченными. Проверьте, что уведомления о публикации доходят до кого-то в команде и что кто-то следит за удалением запусков workflow в журнале аудита.

Что произошло (по сообщениям трёх организаций)

Всё ниже изложено так, как сказано в разборе TanStack, разборе Nx и сообщении GitHub. Время — UTC.

  1. 11 мая 2026, 19:20–19:26

    Через workflow релиза репозитория Router/Start проекта TanStack в npm публикуются 84 вредоносные версии в 42 пакетах.
  2. 11 мая, 19:46

    Внешний исследователь оставляет подробный отчёт в репозитории TanStack. TanStack начинает реагирование.
  3. 11 мая, 20:43

    Участник Nx запускает pnpm install в проекте, не связанном с Nx, и получает вредоносный @tanstack/zod-adapter@1.166.15. По словам Nx, токен GitHub CLI был украден и использован в течение 74 секунд.
  4. 11 мая, к 21:03

    TanStack помечает все 84 версии как устаревшие (deprecated).
  5. 11 мая, 22:13–23:55

    npm удаляет затронутые архивы пакетов из реестра.
  6. 15 мая

    TanStack объявляет отбой тревоги: все опубликованные сейчас версии безопасны.
  7. 18 мая, 12:30–13:09

    С помощью украденного доступа участника в двух каналах распространения расширений публикуется, а затем снимается Nx Console v18.95.0.
  8. 18 мая (понедельник, по времени США)

    GitHub обнаруживает и сдерживает компрометацию устройства сотрудника, связанную с заражённым расширением VS Code, удаляет вредоносную версию расширения и изолирует устройство. Критичные секреты меняются в тот же и на следующий день.
  9. 20 мая

    GitHub сообщает публично: по его оценке, наружу выведены только внутренние репозитории GitHub.
  10. 21 мая

    Nx публикует свой разбор.
  11. 26 мая

    GitHub обновляет публикацию: меняет ключи, включая ключ подписи GitHub Enterprise Server, и перечисляет действия для администраторов.
84 версии
Вредоносные версии TanStack (42 пакета × 2)
~39 мин
Окно, когда была доступна Nx Console v18.95.0 (оба канала вместе)
7 дней
Сколько, по словам Nx, украденный токен был активен в репозиториях Nx
Ничего не нужно
Делать клиентам GitHub Enterprise Cloud (по словам GitHub)
Что раскрыли три организации
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 говорит, что опубликует более полный отчёт, когда расследование завершится; тогда мы обновим эту страницу.

Читать дальше

FAQ

QКакие пакеты TanStack были скомпрометированы?
A

Согласно разбору 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Что делать, если я установил затронутую версию?
A

TanStack настоятельно рекомендует всем, кто установил затронутую версию 11 мая 2026 года (UTC), сменить учётные данные AWS, GCP, Kubernetes, Vault, GitHub, npm и SSH, доступные с машины, где шла установка. Поскольку код выполнялся при установке, в счёт идут не только машины разработчиков, но и раннеры CI.

QЯ использую Nx Console. Меня это затронуло?
A

Согласно разбору 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?
A

По словам GitHub, речь идёт о выводе наружу только внутренних репозиториев GitHub, и у компании нет свидетельств воздействия на информацию клиентов, хранящуюся вне этих репозиториев, например на собственные предприятия, организации и репозитории клиентов. В некоторых внутренних репозиториях всё же есть информация клиентов, например фрагменты обращений в поддержку, и GitHub говорит, что уведомит клиентов по установленным каналам, если воздействие будет обнаружено. Клиентам GitHub Enterprise Cloud ничего делать не нужно.

QЧто нужно сделать администраторам GitHub Enterprise Server?
A

В обновлении от 26 мая GitHub сообщил, что меняет ключи, включая ключ, которым подписываются пакеты обновлений GitHub Enterprise Server, и попросил администраторов сменить открытые ключи GPG в своих экземплярах. Без этой смены будущие обновления не пройдут проверку. Инструкции и дайджест SHA256 вспомогательного скрипта приведены в публикации GitHub. GitHub также просит скачивать обновления GHES только из официального источника.

QСвязаны ли эти три инцидента?
A

Связь TanStack и Nx указана в разборе Nx: 11 мая участник Nx запустил pnpm install в постороннем проекте, получил скомпрометированный @tanstack/zod-adapter 1.166.15, и у него украли токен GitHub CLI. В публикации GitHub «заражённое расширение VS Code», скомпрометировавшее устройство сотрудника, связано ссылкой с бюллетенем безопасности Nx Console.

QКакова была первопричина?
A

В разборе TanStack названы три слабых места, которые сработали только вместе: workflow на pull_request_target собирал код из pull request форков; это задание могло записывать в кэш GitHub Actions, общий с workflow релиза; а workflow релиза мог получить токен OIDC (короткоживущий токен, который выдаётся на каждый запуск CI), используемый для публикации в npm. Nx называет настройку возраста релиза, которую старая версия pnpm молча игнорировала, токен, хранившийся там, где его мог прочитать любой локальный процесс, и пайплайн, позволявший одному человеку опубликовать расширение.