Пакеты TanStack были опубликованы с malware — и путь доверия здесь имеет значение
Источник: Socket Blog — https://socket.dev/blog/tanstack-npm-packages-compromised-mini-shai-hulud-supply-chain-attack?utm_medium=feed
Согласно Socket Threat Research, ряд npm-пакетов в пространстве имён @tanstack был опубликован в компрометированном виде. Socket сообщает, что обнаружила 84 затронутых артефакта пакетов, а вредоносные версии содержали предполагаемый stealer учётных данных, нацеленный на CI-среды, включая GitHub Actions.
Это история про supply-chain, но не совсем обычная. Ключевое утверждение не только в том, что вредоносный код попал в популярные пакеты. Суть в том, что атакующий, похоже, злоупотребил легитимным trust path, связанным с GitHub Actions и OIDC. Если это подтвердится, инцидент станет полезным напоминанием: signed provenance и trusted publishing не помогают, если workflow, которое получает это доверие, само доступно коду, контролируемому атакующим.
Несколько затронутых пакетов широко используются как напрямую, так и транзитивно. Socket отдельно отмечает @tanstack/react-router как пример с очень большим объёмом еженедельных загрузок. Это означает, что blast radius здесь — проблема зависимостей, а не только проблема мейнтейнеров TanStack.
Что известно на данный момент#
Согласно отчёту Socket, компрометированные версии пакетов содержали недавно добавленный файл размером около 2,3 MB. Socket описывает этот файл как сильно обфусцированный и отличающийся от обычного minified JavaScript. Среди характерных признаков перечисляются rotation массива строк, обращения к идентификаторам в hex-стиле, flattening control-flow и внедрение dead code.
Socket также сообщает, что поведение payload включало:
- daemonized execution
- доступ к переменным окружения
GITHUB_* - staging и cleanup временных файлов
- remote streaming или dispatch-поведение
Такая комбинация соответствует импланту для кражи учётных данных или сбора CI-секретов, хотя публичная сводка пока остаётся вторичным источником, и к точным утверждениям о поведении стоит относиться с должной осторожностью, пока не появится больше независимого анализа.
В отчёте также говорится, что некоторые вредоносные версии добавляли git-based ссылку в optionalDependencies на @tanstack/setup, указывая на конкретный Git commit в истории репозитория. Socket называет этот commit подозрительным: отдельный root commit без родительской истории, который добавлял lifecycle hook с запуском bun run tanstack_runner.js && exit 1.
Эта деталь важна, потому что npm lifecycle hooks для git-зависимостей могут автоматически выполняться во время установки. На практике это может превратить установку пакета в выполнение кода на рабочей станции разработчика или в CI.
Вероятный путь атаки#
По данным Socket, TanStack заявила, что npm tokens не были украдены, а обычный workflow публикации в npm не был напрямую скомпрометирован. Вместо этого вредоносные публикации якобы были аутентифицированы через OIDC trusted-publisher binding проекта после того, как код под контролем атакующего выполнился в workflow GitHub Actions.
Socket связывает инцидент с chained-атакой на GitHub Actions, включавшей три элемента:
- паттерн Pwn Request
- cache poisoning GitHub Actions через границу доверия fork-to-base
- runtime extraction of an OIDC token из памяти процесса runner в Actions
Если это так, то именно в этом и заключается важный архитектурный урок.
Сегодня многие команды воспринимают публикацию через OIDC как надёжный ответ на кражу токенов registry. Это действительно улучшение. Но оно не устраняет проблему вредоносного выполнения внутри CI. Если атакующий может пересечь границу доверия внутри workflow, он может получить возможность выпустить те же артефакты доверия, которые сгенерировала бы настоящая сборка.
Поэтому этот инцидент не стоит сводить к формуле «ещё один вредоносный npm-пакет». Это ещё и предупреждение о том, насколько сильно организации полагаются на CI identity, поведение cache и композицию workflow.
Почему это особенно серьёзно#
TanStack — это не малоизвестная инфраструктура. Её пакеты глубоко находятся внутри деревьев зависимостей JavaScript и попадают во множество проектов так, что разработчики часто даже не смотрят на них напрямую.
Это меняет оценку риска в двух аспектах.
Во-первых, главной проблемой становится транзитивная экспозиция. Команда может не устанавливать затронутый пакет TanStack сознательно и всё равно подтянуть его в CI через другую зависимость.
Во-вторых, меняется профиль цели. Имплант, который охотится за переменными GITHUB_* и другими учётными данными, пытается скомпрометировать не просто локальную dev-машину. Он пытается продвинуться вверх по цепочке — к репозиториям, путям публикации пакетов, cloud credentials и, возможно, downstream customers.
Socket прямо предупреждает от избыточного доверия к бейджам provenance Sigstore в таком сценарии. Логика проста: если атакующий может выполнять код внутри доверенного контекста GitHub Actions, он может получить возможность сгенерировать валидный provenance для вредоносной публикации. У provenance по-прежнему есть ценность, но он не может заменить hardening workflow.
Что, как сообщается, сделала TanStack#
По данным Socket, проект начал меры по сдерживанию последствий: отзывал затронутые публикации, выпускал безопасные версии и занимался восстановлением доверенной цепочки релизов. В подобных инцидентах это правильный первый шаг, но для потребителей пакетов этого недостаточно: каждой команде всё равно нужно самостоятельно проверить, не успели ли вредоносные версии попасть в lockfile, кэш сборки или внутренний registry mirror.
Практический вывод для команд#
Самый полезный вывод здесь не в абстрактном «укрепляйте supply-chain», а в конкретной проверке своих CI-процессов уже сейчас.
Что стоит сделать немедленно:
- Проверьте lockfile и историю сборок на наличие затронутых версий
@tanstackи связанных git-зависимостей. - Сбросьте потенциально скомпрометированные секреты, если CI мог устанавливать эти пакеты: GitHub tokens, npm credentials, cloud keys, deploy keys.
- Очистите кэши CI и пересоберите артефакты из доверенного состояния, потому что вредоносный код и побочные файлы могли сохраниться в cache layers.
- Запретите исполнение непроверенного кода в привилегированных workflow: разделите jobs для PR из forks и jobs, которые имеют доступ к секретам, релизам и OIDC.
- Минимизируйте
permissions:в GitHub Actions и выдавайтеid-token: writeтолько тем job, которым он действительно нужен для публикации. - Пересмотрите использование cache между недоверенными и доверенными контекстами, чтобы исключить fork-to-base poisoning.
- Добавьте детектирование аномалий в публикации: неожиданные git-зависимости, новые lifecycle hooks, крупные обфусцированные файлы, резкий рост package size.
Коротко: OIDC trusted publishing — это не финальный контроль, а лишь более безопасный способ выдачи полномочий. Если ваш release workflow может выполнить код атакующего, он сможет и «честно» подписать вредоносный релиз. Главная защита — не только provenance, а жёсткая изоляция workflow, минимальные права и недоверие к коду из внешних PR до прохождения безопасной границы проверки.