Back

Автоматизация проверки безопасности npm-пакетов с помощью npq

Автоматизация проверки безопасности 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 и разовый аудит

Установите 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.

OpenReplay