Автоматизация проверки безопасности npm-пакетов с помощью npq
npq выполняет аудит npm-пакета до его установки, тогда как npm audit сообщает об уязвимостях лишь после того, как код уже записан в node_modules. В этом и состоит ключевое различие: к моменту, когда кто-либо проверяет дерево зависимостей, вредоносный скрипт postinstall уже мог выполниться на вашей машине. npq переносит проверку на более ранний этап — он анализирует метаданные пакета, его возраст, скрипты и известные CVE ещё на этапе запроса установки, а затем спрашивает, хотите ли вы продолжить.
В этом руководстве описывается, как интегрировать npq в терминал и pre-commit хук, чтобы аудит выполнялся там, где вы подключаете зависимости, — а не только тогда, когда вы вспомните о нём.
npm install -g npq
Ключевые выводы
npm auditработает с пакетами, уже записанными вnode_modules; npq перехватывает запрос на установку до того, как какой-либо код попадёт на ваш диск.npq-hero— это встроенная замена npm-обёртки, устанавливаемая вместе с npq; создавайте псевдонимnpmименно дляnpq-hero(а не дляnpqнапрямую), чтобы сохранить поддержку всех подкоманд npm.- По умолчанию npq ожидает 15 секунд, а затем автоматически продолжает установку, если обнаружены только предупреждения. Установите
NPQ_DISABLE_AUTO_CONTINUE=trueили передайте флаг--disable-auto-continue, чтобы заменить обратный отсчёт явным запросом(y/N). Это интерактивная проверка, а не автоматический CI-барьер. - Запуск
npqбез подкомандыinstallв директории проекта выполняет аудит всех зависимостей изpackage.json— полезно перед открытием pull request, добавляющего или обновляющего зависимости. - Маршаллы npq — это эвристические сигналы, а не доказательство злого умысла: пакет, опубликованный вчера с нулевым числом загрузок, срабатывает по проверкам возраста и популярности, однако именно с этого начинает каждый легитимный новый пакет.
Какую проблему решает npq
npq — это аудитор безопасности, работающий до установки пакетов. Он запускает набор проверок — называемых «маршаллами» — против метаданных пакета ещё до того, как npm загрузит и выполнит какой-либо код. Это противоположность npm audit, который читает уже установленное дерево зависимостей и сообщает о CVE постфактум. Кампания Shai-Hulud 2025 года использовала lifecycle-скрипты, выполняемые в процессе установки, — именно то временно́е окно, которое npm audit не может закрыть, а npq может. Инструмент с открытым исходным кодом доступен по адресу lirantal/npq и разработан Лираном Талом.
Установка npq и разовый аудит
Discover how at OpenReplay.com.
Установите npq глобально, затем используйте npq install вместо npm install для любого пакета, который хотите проверить заранее.
npm install -g npq
npq install express
Пакет npq на npm устанавливает два бинарных файла: npq и npq-hero. Первый выполняет явный аудит; второй — встроенная npm-обёртка, рассматриваемая в следующем разделе. При запуске npq install express инструмент получает метаданные, запускает маршаллы, выводит результаты и — если что-то помечено как подозрительное — запрашивает подтверждение перед передачей управления npm.
Вывод для помеченного пакета выглядит примерно следующим образом:
warning Package has install scripts (preinstall, postinstall)
warning Package is older than 22 days? no — published 1 day ago
? Would you like to continue installing package(s)? (Y/n)
Запрос — это точка контроля. Ничего не устанавливается до тех пор, пока вы не ответите, или пока не истечёт 15-секундный таймер автопродолжения при наличии только предупреждений.
Создание псевдонима npm для npq-hero и его сохранение
Чтобы аудит выполнялся автоматически при каждой установке, создайте псевдоним npm для npq-hero и добавьте его в конфигурационный файл вашей оболочки. npq-hero — это обёртка, созданная именно для этой цели: она прозрачно передаёт все подкоманды npm (run, ci, publish и прочие) без изменений, перехватывая только установки для предварительного аудита.
echo "alias npm='npq-hero'" >> ~/.zshrc # или ~/.bashrc для bash
source ~/.zshrc
После добавления псевдонима команда npm install fastify будет проходить через маршаллы npq до того, как npm загрузит tarball. Создавайте псевдоним npm именно для npq-hero, а не для npq напрямую: npq — это бинарный файл аудита, тогда как npq-hero — полноценная npm-совместимая обёртка с поддержкой passthrough, задокументированная в README npq. Псевдоним для бинарного файла npq сломает подкоманды, которые npq самостоятельно не реализует.
Что именно проверяет npq?
npq выполняет набор проверок безопасности — «маршаллов», задокументированных в README npq. Они разделены на четыре практические категории:
| Категория | Что проверяется |
|---|---|
| Сигналы цепочки поставок | Известные уязвимости (через OSV или Snyk при наличии настройки), верификация подписи реестра, аттестация происхождения сборки |
| Индикаторы вредоносности | Наличие скриптов preinstall/postinstall, тайпсквоттинг популярных пакетов, появление новых бинарных файлов или CLI |
| Состояние пакета | Отсутствие README, LICENSE или URL репозитория; сигналы устаревания; количество загрузок |
| Сигналы мейнтейнеров | Количество мейнтейнеров и контактные данные, просроченные или недействительные домены мейнтейнеров, возраст пакета (обнаружение новых пакетов) и зрелость версии |
Такая группировка отражает реальную картину атаки: тайпсквот со скриптом postinstall и нулевым числом загрузок одновременно срабатывает по нескольким маршаллам. Каждая проверка — это сигнал, который вы оцениваете, а не бинарный вердикт: npq предоставляет данные и передаёт решение вам.
Отключение автопродолжения для явной проверки
По умолчанию интерактивный запрос npq ожидает 15 секунд, а затем автоматически продолжает установку, если обнаружены только предупреждения. Установите NPQ_DISABLE_AUTO_CONTINUE=true или передайте флаг --disable-auto-continue, чтобы убрать обратный отсчёт и потребовать явного ответа (y/N) перед передачей управления npm. Оба варианта задокументированы в README npq.
# Оба варианта работают
NPQ_DISABLE_AUTO_CONTINUE=true npq install
npq install --disable-auto-continue
Это превращает npq в осознанный шаг проверки — полезный как в терминале, так и внутри git commit хука, где кто-то присутствует, чтобы ответить на запрос. Это не задокументированный режим неинтерактивного завершения с ошибкой: запрос по-прежнему ожидает ответа, и npq не предоставляет флага, который автоматически преобразует каждый помеченный пакет в ненулевой код завершения.
Маршрутизация pnpm через npq
npq делегирует управление менеджеру пакетов, указанному в NPQ_PKG_MGR, поэтому тот же уровень аудита распространяется и на pnpm. Устанавливайте переменную для разовых команд или добавьте её в псевдоним оболочки для ежедневного использования.
# Разовый аудит через pnpm
NPQ_PKG_MGR=pnpm npq install fastify
# Маршрутизация всех pnpm-установок через npq
alias pnpm="NPQ_PKG_MGR=pnpm npq-hero"
echo 'alias pnpm="NPQ_PKG_MGR=pnpm npq-hero"' >> ~/.zshrc
Переменная NPQ_PKG_MGR, перечисленная в README npq, указывает npq-hero, какой менеджер пакетов вызвать после успешного прохождения аудита. Псевдоним даёт те же гарантии для pnpm, что псевдоним npm даёт для npm: ни одна установка не начнётся до выполнения маршаллов.
Добавление pre-commit хука husky
Перехватывайте небезопасные зависимости до их коммита, запуская npq из pre-commit хука husky. Это выполняет аудит зависимостей, объявленных в package.json, при каждом коммите — что особенно ценно для коммитов, затрагивающих манифесты зависимостей.
Установите husky и инициализируйте его (синтаксис husky v9):
npm install --save-dev husky
npx husky init
Затем добавьте хук в .husky/pre-commit:
# .husky/pre-commit
if git diff --cached --name-only | grep -qE 'package(-lock)?\.json'; then
npx npq
fi
Проверка git diff --cached ограничивает аудит коммитами, которые действительно изменяют package.json или package-lock.json, чтобы несвязанные коммиты не несли накладных расходов аудита. Команда npx npq без подкоманды install проверяет зависимости, объявленные в package.json, и завершается с ненулевым кодом при обнаружении проблем. Поскольку Husky блокирует коммиты при ненулевом завершении хука, это превращает хук в жёсткий pre-commit барьер. Команда npx husky init и формат скрипта .husky/pre-commit соответствуют соглашениям husky v9; в v8 использовался другой синтаксис husky add, поэтому перед копированием устаревших фрагментов убедитесь в установленной версии.
Честные ограничения: эвристика, а не доказательство
Маршаллы npq — это эвристические сигналы, а не доказательство злого умысла. Пакет, опубликованный вчера с нулевым числом загрузок, вызывает подозрение по проверкам возраста и популярности npq — однако именно с этого начинает каждый легитимный новый пакет. npq сводит шум к набору взвешенных сигналов и передаёт решение вам; он не может и не претендует на классификацию намерений. Воспринимайте помеченную установку как повод изучить пакет, а не как подтверждённую угрозу.
npq также не заменяет npm audit или Socket — он дополняет их. Три инструмента закрывают разные временны́е окна:
| Инструмент | Когда запускается | Что проверяет | Нативная поддержка CI |
|---|---|---|---|
| npq | До установки | Возраст, install-скрипты, тайпсквоттинг, известные CVE через OSV (или Snyk) | Нет — работает интерактивно |
npm audit | После установки | CVE в уже установленных пакетах | Да (встроен) |
| Socket | Непрерывно | Поведенческий анализ графа зависимостей, мониторинг после слияния | Да (приложение + CLI) |
npq перехватывает сигналы до установки; npm audit выявляет CVE в пакетах, уже находящихся на диске; Socket добавляет непрерывный поведенческий мониторинг графа зависимостей после слияния. Сочетание install-time барьера npq с --ignore-scripts в качестве настройки по умолчанию (и таких инструментов, как LavaMoat allow-scripts, для зависимостей, которым действительно нужны lifecycle-скрипты) закрывает большую часть поверхности атаки на этапе установки.
Заключение
Создание псевдонима npm для npq-hero и блокировка коммитов с помощью husky-хука обеспечивает единый pre-install аудит во всех точках подключения зависимостей — в локальном терминале и при коммите. Начните с глобальной установки и псевдонима оболочки, затем добавьте husky-хук в следующий раз, когда будете работать с манифестами зависимостей. Маршаллы — это эвристика, поэтому читайте то, что они помечают: изучить предупреждение куда лучше, чем обнаружить postinstall-нагрузку уже после её выполнения.
Часто задаваемые вопросы
Не в том виде, который документирует проект. Установка NPQ_DISABLE_AUTO_CONTINUE=true или передача флага --disable-auto-continue убирает 15-секундное автопродолжение и требует явного ответа (y/N), однако запрос по-прежнему ожидает ответа. Не существует задокументированного флага, который автоматически преобразует каждый помеченный пакет в ненулевой код завершения. Надёжные сценарии использования npq — интерактивные: в терминале через псевдоним npq-hero и при коммите через husky-хук, где вы присутствуете, чтобы ответить на запрос.
npq и npq-hero — это два отдельных бинарных файла, устанавливаемых вместе. npq — явная команда аудита, используемая вместо npm install. npq-hero — полноценная npm-совместимая обёртка: она прозрачно передаёт все подкоманды npm, такие как run, ci и publish, без изменений, перехватывая только установки для предварительного аудита. Псевдоним npm для бинарного файла npq напрямую сломает подкоманды, которые npq не реализует, поэтому README рекомендует использовать псевдоним для npq-hero.
npq работает с pnpm через переменную окружения NPQ_PKG_MGR. Установка NPQ_PKG_MGR в значение pnpm указывает npq-hero, какой менеджер пакетов вызвать после успешного прохождения аудита. Можно устанавливать её для отдельных команд, например NPQ_PKG_MGR=pnpm npq install fastify, или добавить в псевдоним оболочки, например alias pnpm='NPQ_PKG_MGR=pnpm npq-hero', чтобы все pnpm-установки проходили через маршаллы npq.
Используйте оба инструмента, поскольку они закрывают разные временны́е окна. npq запускается до установки и проверяет возраст пакета, lifecycle-скрипты, тайпсквоттинг и данные об известных уязвимостях через OSV (или Snyk при наличии настройки), предотвращая попадание вредоносного кода на диск. npm audit запускается после установки и сообщает о CVE в пакетах, уже записанных в node_modules. npq закрывает поверхность атаки на этапе установки, которую npm audit не может охватить, тогда как npm audit остаётся полезным для текущего отслеживания CVE в установленных зависимостях.
Understand every bug
Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.