Supply chain атаки в npm: разбор инцидентов 2026 и защита проекта

Реальные компрометации npm в 2026 (axios, TanStack, Mastra AI): как устроены supply chain атаки и конкретный чеклист защиты проекта.

Supply chain атаки в npm: разбор инцидентов 2026 и защита проекта

Supply chain атаки в npm: разбор инцидентов 2026 и защита проекта

Первые полгода 2026 года выдались богатыми на неприятные инциденты в npm: список скомпрометированных пакетов вышел непривычно длинным. Например, в конце марта злоумышленники подменили axios — библиотеку, которую скачивают десятки миллионов раз в неделю, — и на несколько часов она распространяла вредоносный код. В мае появились десятки заражённых версий пакетов из экосистемы TanStack. А в середине июня мы разбирали атаку, затронувшую сразу больше сотни пакетов, связанных с одной ИИ-библиотекой. И это только то, что попало в заголовки.

Мы в Quillon разбираем эти инциденты со студентами не для того, чтобы напугать, а потому что защита от них — это несколько конкретных инженерных привычек — из тех, что достаточно выработать однажды и больше про них не думать. Дальше — как эти атаки устроены и что реально снижает риск.

Почему npm стал такой удобной мишенью

Современный фронтенд- или node-проект — это уже не только ваш код. Это ваш код вместе с сотнями, а то и тысячами чужих пакетов, которые подтягиваются автоматически. Вы установили один фреймворк, а он притащил за собой полсотни зависимостей, каждая из которых привела за собой ещё десяток. В node_modules типичного проекта легко насчитывается тысяча и больше пакетов, созданных сотнями разных людей, которых вы, скорее всего, никогда не видели.

Каждый из этих людей — потенциальная точка входа. Атакующему не нужно ломать ваш проект напрямую. Достаточно получить контроль над одним популярным пакетом где-то глубоко в дереве зависимостей, и его код автоматически появится на машинах всех, кто этот пакет использует. Прямо или косвенно.

Такие атаки называют supply chain: удар идёт не по самому проекту, а по звену, которому он доверяет. Ломать хорошо защищённый вход не нужно — достаточно найти тот, что никто не сторожит.

Как именно это происходит

За инцидентами 2026 года стоят несколько типичных сценариев — вот основные.

Компрометация мейнтейнера. Самый распространённый способ. У человека, который поддерживает популярный пакет, воруют доступ: через фишинг, утечку токена npm или переиспользованный пароль. Затем атакующий публикует новую версию от его имени. Так было и с axios: чистая библиотека неожиданно получила обновление, которое не добавляло ничего полезного, а вместо этого выполняло вредоносный код. Пользователи с включённым автообновлением минорных версий получили заражённый код, даже не подозревая об этом.

Отравление CI и кража токенов. История с пакетами TanStack сложнее. Там атакующий не взламывал напрямую аккаунт мейнтейнера. Он использовал уязвимость в настройке GitHub Actions — так называемый Pwn Request, когда воркфлоу выполняет код из чужого pull request с избыточными правами. Это позволило отравить кэш сборки и получить доступ к токену, используемому для публикации в npm. А дальше — десятки вредоносных версий, выпущенных легальным автоматическим конвейером. Формально всё выглядело как обычный релиз.

Typosquatting. Классика, которая никуда не делась. Атакующий регистрирует пакет с названием, похожим на популярное: меняет порядок букв, убирает дефис или добавляет -js. Кто-то опечатается в package.json или при npm install и вместо настоящей библиотеки получит подделку. Особенно опасно в связке с ИИ-ассистентами: модель может случайно «вспомнить» несуществующее имя пакета, а атакующий заранее зарегистрирует это имя с вредоносным кодом.

Вредоносные postinstall-скрипты. npm позволяет выполнять произвольные скрипты сразу после установки пакета — до запуска вашего кода. Это удобно для легальных задач (например, сборки нативного модуля), но и служит каналом доставки вредоносного кода: заражённый пакет крадёт переменные окружения, токены и SSH-ключи прямо во время npm install, ещё до того, как вы что-либо заметите.

Что реально снижает риск

Стопроцентной защиты не существует — если вы используете чужой код, вы принимаете часть чужого риска. Но поверхность атаки можно заметно уменьшить, и это не так сложно, как кажется. Нужно просто выработать несколько привычек.

Фиксируйте зависимости и используйте lockfile. package-lock.json должен храниться в репозитории и проходить ревью. На CI и в проде используйте npm ci, а не npm install: первая команда устанавливает ровно то, что есть в lockfile, и выдаёт ошибку при расхождениях. Вторая может тихо подтянуть обновление. С npm ci сборка на CI и на машине разработчика получается одинаковой; npm install может тихо подтянуть другую версию, и поймать это потом сложно.

Не обновляйтесь сразу после релиза. Большинство атак живут в реестре всего несколько часов или дней, пока их не обнаружат и удалят. Если вы не накатываете свежие версии в момент их появления, а даёте им полежать хотя бы несколько дней, то просто избежите периода, когда заражённая версия ещё доступна в npm. Автообновление минорных и патч-версий на проде — плохая идея именно по этой причине.

Отключайте установочные скрипты, если это возможно. Флаг --ignore-scripts запрещает пакетам выполнять postinstall при установке. Это не всегда проходит без проблем (некоторые зависимости действительно собирают нативный код), но на CI его стоит использовать и разрешать скрипты только для тех пакетов, которым они действительно нужны.

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

Проверяйте происхождение. npm поддерживает provenance — подтверждение того, что пакет собран в конкретном публичном CI из конкретного коммита, а не загружен вручную. Это не панацея — история с TanStack как раз показала, что при угоне самого конвейера сборки вредоносный релиз получает вполне валидное подтверждение происхождения. Но в типовых сценариях с угоном аккаунта мейнтейнера провенанс усложняет подделку. Если вы публикуете свои пакеты, включить его тоже стоит.

Разделяйте и ограничивайте токены. Токен для публикации в npm не должен быть легкодоступен и иметь только те права, которые необходимы для этой задачи. Отдельные токены с минимальными правами и ограниченным сроком действия — может, и скучновато, но именно кража одного токена с широкими правами лежит в основе половины этих атак.

Это не только про npm

Всё, о чём мы говорили, почти дословно применимо к PyPI и питоновскому миру. Там тоже случаются громкие истории с заражёнными пакетами, typosquatting и вредоносными скриптами в setup.py. Разница лишь в командах и деталях, но принцип один: вы доверяете дереву чужого кода, и управление этим доверием — часть работы инженера, а не отдельного отдела безопасности.

На наших курсах по Python и QA Automation мы разбираем это как часть обычной инженерной работы. Ставки понятны: один заражённый пакет в дереве зависимостей способен слить токены и ключи, а заметить это можно уже постфактум.

Что сделать сегодня

Если не хочется сразу перестраивать весь процесс, начните с трёх простых шагов. Убедитесь, что lockfile хранится в репозитории и на CI используется npm ci. Отключите автообновление зависимостей на проде. И посмотрите на своё дерево зависимостей — возможно, половину пакетов можно удалить без каких-либо потерь.

Остальное — provenance, --ignore-scripts, разделение токенов — можно настроить позже. Но эти три пункта помогут нейтрализовать самые распространённые сценарии, которые мы видели в 2026 году, и занимают всего один вечер.

Хочешь войти в IT за 12 месяцев?

Выбери трек — Python, Flutter или QA — и начни с бесплатного вводного урока

Выбрать трек