Supply Chain Attack: как положить полмира через одну npm-библиотеку
Привет, друг!
Представь: ты не ломаешь Google, Microsoft или банк напрямую. Ты взламываешь маленькую библиотеку с 2 миллионами загрузок в неделю — и получаешь доступ к сотням тысяч проектов сразу. Это и есть Supply Chain Attack — элегантная, жестокая и крайне эффективная атака на цепочку поставок ПО.
Что вообще происходит
Supply Chain Attack (атака на цепочку поставок) — это компрометация не конечной цели, а инструмента, которым пользуется жертва. В экосистеме npm это выглядит так: злоумышленник внедряет вредоносный код в популярный пакет, и все, кто его устанавливает, автоматически запускают малварь у себя на машине или в CI/CD пайплайне.
Атакующий эксплуатирует главную слабость современной разработки — слепое доверие к зависимостям. Среднее Node.js-приложение тащит за собой сотни транзитивных зависимостей. Никто их не читает. Никто не аудитирует. Просто npm install — и поехали.
Реальный кейс: червь Shai-Hulud (2025)
В сентябре 2025 года случился один из крупнейших инцидентов в истории npm — самораспространяющийся червь Shai-Hulud заразил свыше 500 пакетов. Наиболее серьёзной жертвой стал пакет @ctrl/tinycolor с 2 миллионами загрузок в неделю.
Анатомия атаки — пошагово
Шаг 1 — Начальное заражение.
Злоумышленник публикует или компрометирует существующий пакет, добавляя в package.json хук postinstall:
|
1 2 3 4 5 |
{ "scripts": { "postinstall": "node bundle.js" } } |
Этот скрипт запускается автоматически при каждом npm install. Без предупреждений, без подтверждений.
Шаг 2 — Разведка на машине жертвы.bundle.js весом >3 МБ запускается и собирает:
- Информацию об ОС (Linux/macOS — основная цель)
- npm-токены из переменных окружения
- GitHub-токены аутентификации
Если GitHub-токен не найден — скрипт завершает работу, не светясь лишний раз.
Шаг 3 — Кража секретов.
Используя встроенный TruffleHog (легитимный инструмент для поиска секретов), червь сканирует репозитории жертвы на AWS-ключи, GCP-токены, API-ключи. Все данные агрегируются в data.json и улетают на сервер атакующего.
Шаг 4 — Слив приватных репозиториев.
Через GitHub API все приватные репозитории жертвы помечаются как публичные. Это иногда важнее кражи токенов — исходники компании утекают мгновенно.
Шаг 5 — Саморепликация (самое интересное).
Именно здесь Shai-Hulud становится червём, а не просто малварью:
|
1 2 3 4 5 6 7 8 |
1. Получить список 20 самых скачиваемых пакетов жертвы через npm API 2. Для каждого пакета: a. Скачать текущий tarball (.tar) b. Распаковать во временную директорию npm-update-{package} c. Внедрить вредоносный bundle.js d. Добавить postinstall hook в package.json e. Увеличить версию пакета на 1 f. npm publish — опубликовать заражённый пакет |
Итог: жертва сама того не зная распространяет червя дальше через свои собственные легитимные пакеты.
Другие техники Supply Chain в npm
Shai-Hulud — не единственный вектор. Вот полный арсенал атакующего:
| Техника | Суть | Пример |
|---|---|---|
| Typosquatting | Регистрация пакета с опечаткой (lodahs вместо lodash) | cros-env vs cross-env |
| Dependency Confusion | Публикация пакета с именем внутренней зависимости компании | Атака Alex Birsan, 2021 |
| Account Takeover | Угон npm-аккаунта мейнтейнера и публикация вредоноса | event-stream (2018) |
| Star Jacking | Кража популярности у известного пакета | Актуально для PyPI/npm |
| CI/CD Poisoning | Внедрение кода через GitHub Actions в чужой репозиторий | Shai-Hulud + Actions |
Как это защищать — конкретные шаги
На уровне разработки:
- Используй
package-lock.jsonи никогда не игнорируй его в.gitignore— он фиксирует точные версии - Включи
npm auditв CI пайплайн как обязательный шаг - Минимизируй зависимости: 10 строк своего кода надёжнее чем
npm install left-pad
На уровне токенов и секретов:
|
1 2 3 4 5 |
# Проверь, не утекли ли твои npm-токены npm token list # Настрой granular tokens с минимальными правами # GitHub теперь поддерживает fine-grained tokens |
На уровне мониторинга:
- Аудит GitHub Actions на наличие веток
shai-huludили подозрительных workflows - Ротация всех секретов после любого подозрительного инцидента: npm-токены, GitHub-токены, AWS/GCP ключи
- Используй инструменты типа Socket.dev или Snyk для анализа новых зависимостей перед установкой
На уровне CI/CD:
|
1 2 3 4 5 6 7 8 9 |
# .github/workflows/security.yml - name: Audit dependencies run: | npm audit --audit-level=high npx better-npm-audit audit - name: Check for suspicious postinstall run: | cat package.json | jq '.scripts.postinstall' |
Проверь свои пакеты прямо сейчас:
|
1 2 3 4 5 |
# Ищем подозрительные postinstall hooks во всех зависимостях cat node_modules/*/package.json | \ python3 -c "import sys,json; \ [print(d) for d in [json.loads(l) for l in sys.stdin if l.strip()] \ if d.get('scripts',{}).get('postinstall')]" |
Масштаб проблемы
GitHub уже анонсировал ужесточение безопасности npm: строгая аутентификация, granular tokens и улучшенный мониторинг публикаций. Но реальность такова: npm-реестр содержит миллионы пакетов, а команда безопасности физически не может проверить каждый.
Supply Chain Attack — это атака на доверие. И пока разработчики слепо доверяют npm install, злоумышленники будут этим пользоваться. Один скомпрометированный мейнтейнер с популярным пакетом = потенциальный доступ к инфраструктуре тысяч компаний. Это не страшилки — это то, что уже произошло в 2025 году с @ctrl/tinycolor.

На этом все. Всем хорошего дня!
