Проблема
Supply-chain атака через npm больше не выглядит как редкий edge-case. Маленький пакет может оказаться точкой входа в рабочую машину разработчика, CI-контур или браузерный профиль, где живут токены, расширения и следы доступа к SaaS-инструментам.
Опасность не только в самом пакете. Опасность в доверии к install-time действиям, в неразделённых профилях браузера и в том, что developer endpoint часто имеет больше доступа к продукту, чем обычный офисный ноутбук.
Что проверить
- Есть ли запрет или аудит install scripts в npm/pnpm/yarn для production и CI.
- Отделены ли рабочие браузерные профили от личных и тестовых расширений.
- Можно ли быстро отозвать npm tokens, Git tokens, cloud keys и OAuth grants после подозрительного install.
- Логируются ли обращения к секретам и скачивание зависимостей в CI.
- Есть ли allowlist registry/proxy и lockfile review для критичных репозиториев.
Решение
Минимальная зрелая защита начинается с dependency proxy, lockfile-diff review, запрета неожиданных postinstall hooks и отдельной политики для developer workstations.
Для SOC полезнее не алерт на слово stealer, а корреляция: новый пакет, запуск неизвестного node-процесса, чтение browser storage, сетевой выход к новому домену, затем обращение к репозиториям или SaaS.
Defensive-чеклист
- Проверить npmrc и registry policy.
- Включить secret scanning на репозиториях и CI artifacts.
- Ротировать developer tokens при любом подтверждённом подозрительном install.
- Выделить browser extension storage как forensic source, но не складывать сырые токены в отчёты.
- Добавить tabletop-сценарий: malicious package на машине разработчика.
Безопасный пример
# безопасная проверка lockfile: ищем lifecycle scripts без выполнения пакетов
import json
from pathlib import Path
package = json.loads(Path("package.json").read_text(encoding="utf-8"))
scripts = package.get("scripts", {})
for name in ("preinstall", "install", "postinstall", "prepare"):
if name in scripts:
print(f"review_required: {name} -> {scripts[name]}")