Back

npqによるnpmパッケージセキュリティチェックの自動化

npqによるnpmパッケージセキュリティチェックの自動化

npqはnpmパッケージをインストール前に監査しますが、npm auditはコードがすでにnode_modulesに書き込まれた後にしか脆弱性を報告しません。この順序の違いこそが重要です。依存関係ツリーを監査する頃には、悪意のあるpostinstallスクリプトがすでにマシン上で実行されている可能性があるからです。npqはチェックをより上流に移動させます。インストールリクエスト時点でパッケージのメタデータ、公開日時、スクリプト、既知のCVEを検査し、続行するかどうかを確認します。

本ガイドでは、npqをターミナルおよびpre-commitフックに組み込み、依存関係を取得する場所で監査が実行されるようにします。思い出したときだけ実行するのではなく、常に自動的に監査が走る環境を構築します。

npm install -g npq

重要なポイント

  • npm auditはすでにnode_modulesに書き込まれたパッケージに対して実行されますが、npqはコードがディスクに触れる前にインストールリクエストを傍受します。
  • npq-heroはnpqと一緒にインストールされるnpmのドロップイン・ラッパーです。npmのエイリアスはnpqに直接ではなくnpq-heroに設定してください。これにより、すべてのnpmサブコマンドのパススルー動作が維持されます。
  • デフォルトでは、警告のみが存在する場合、npqは15秒待機した後にインストールを自動的に続行します。NPQ_DISABLE_AUTO_CONTINUE=trueを設定するか、--disable-auto-continueを渡すことで、カウントダウンを明示的な(y/N)プロンプトに置き換えられます。これはインタラクティブなレビューであり、CI環境での自動ゲートではありません。
  • プロジェクトディレクトリでnpqをサブコマンドなしで実行すると、package.json内のすべての依存関係が監査されます。依存関係を追加・アップグレードするプルリクエストを開く前に活用できます。
  • npqのmarshallはヒューリスティックなシグナルであり、悪意の証明ではありません。前日に公開されダウンロード数がゼロのパッケージはnpqの年齢・人気度チェックに引っかかりますが、正当な新しいパッケージはすべてそこからスタートします。

npqが埋めるギャップ

npqはインストール前のセキュリティ監査ツールであり、「marshall」と呼ばれる一連のチェックを、npmがコードをフェッチ・実行する前にパッケージのメタデータに対して実行します。これはnpm auditとは逆のアプローチです。npm auditはインストール済みの依存関係ツリーを読み込み、事後的にCVEを報告します。2025年のShai-Huludキャンペーンでは、インストール中に実行されるライフサイクルスクリプトが悪用されました。これはまさにnpm auditがカバーできず、npqがカバーできる窓口です。このツールはlirantal/npqとしてオープンソースで公開されており、Liran Talによって開発されています。

npqのインストールとワンタイム監査の実行

npqをグローバルにインストールし、事前に検証したいパッケージにはnpm installの代わりにnpq installを使用します。

npm install -g npq
npq install express

npmのnpqパッケージnpqnpq-heroの2つのバイナリをインストールします。前者は明示的な監査を実行し、後者は次のセクションで説明するnpmのドロップイン・ラッパーです。npq install expressを実行すると、npqはメタデータをフェッチし、marshallを実行し、検出結果を出力します。何かがフラグされた場合は、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にエイリアス設定して永続化する

すべてのインストールを自動的に監査するには、npmnpq-heroにエイリアス設定し、そのエイリアスをシェル設定ファイルに書き込みます。npq-heroはこの用途向けに設計されたラッパーです。runcipublishなどすべてのnpmサブコマンドをそのままパススルーし、インストール時のみ傍受して先に監査を実行します。

echo "alias npm='npq-hero'" >> ~/.zshrc   # bashの場合は ~/.bashrc
source ~/.zshrc

エイリアスを設定すると、npm install fastifyはnpmがtarballをフェッチする前にnpqのmarshallを経由するようになります。npmのエイリアスはnpqに直接ではなくnpq-heroに設定してください。npqは監査バイナリであり、npq-heronpq READMEに記載されている完全なnpm互換パススルー・ラッパーです。生のnpqバイナリにエイリアスすると、npqが実装していないサブコマンドが動作しなくなります。

npqが実際にチェックする内容

npqは「marshall」と呼ばれる一連のセキュリティチェックを実行します。これらはnpq READMEに記載されており、4つの実用的なカテゴリに分類されます:

カテゴリフラグする内容
サプライチェーンシグナル既知の脆弱性(OSV経由、または設定時はSnyk経由)、レジストリ署名の検証、ビルドプロビナンスの証明
マルウェア指標preinstall/postinstallスクリプトの存在、人気パッケージのタイポスクワット類似品、新しいバイナリ/CLIの導入
パッケージの健全性READMEの欠如、LICENSEの欠如、リポジトリURLの欠如、非推奨シグナル、ダウンロード数
メンテナーシグナルメンテナー数と連絡先情報、期限切れまたは無効なメンテナードメイン、パッケージの公開日時(新規パッケージ検出)とバージョンの成熟度

このように分類することで、攻撃が実際にどのように表面化するかがわかります。postinstallスクリプトを持ちダウンロード数がゼロのタイポスクワットは、複数のmarshallに同時に引っかかります。各チェックは二値的な判定ではなく、重み付けされたシグナルです。npqはデータを提示し、判断をあなたに委ねます。

明示的なレビューのために自動続行を無効化する

デフォルトでは、npqのインタラクティブプロンプトは15秒待機し、警告のみの場合はインストールを自動的に続行します。NPQ_DISABLE_AUTO_CONTINUE=trueを設定するか、--disable-auto-continueを渡すことで、カウントダウンを削除し、npqがnpmに処理を渡す前に明示的な(y/N)の回答を強制できます。フラグと環境変数の両方がnpq READMEに記載されています。

# どちらの形式でも動作します
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 READMEに記載されているNPQ_PKG_MGR変数は、監査が通過した後にどのパッケージマネージャーを呼び出すかをnpq-heroに伝えます。エイリアス形式を使用することで、npmエイリアスがnpmに提供するのと同じ保証がpnpmにも適用されます。marshallが実行されるまで、いかなるインストールも進行しません。

huskyのpre-commitフックを追加する

huskyのpre-commitフックからnpqを実行することで、リスクのある依存関係がコミットされる前に検出できます。これにより、コミット時に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 npqpackage.jsonで宣言された依存関係を監査し、問題が見つかった場合は非ゼロで終了します。Huskyはフックが非ゼロで終了するとコミットをブロックするため、このフックはハードなpre-commitゲートとして機能します。npx husky initコマンドと.husky/pre-commitのベアスクリプト形式はv9 huskyの規約です。v8では異なるhusky add構文が使用されていたため、古いスニペットをコピーする前にインストールされているバージョンを確認してください。

正直な制限事項:ヒューリスティックであり、証明ではない

npqのmarshallはヒューリスティックなシグナルであり、悪意の証明ではありません。前日に公開されダウンロード数がゼロのパッケージは、npqの年齢・人気度チェックでは疑わしいと判定されます。しかし、正当な新しいパッケージはすべてまさにその状態からスタートします。npqはノイズを重み付けされたシグナルのセットに絞り込み、判断をあなたに委ねます。意図を分類することはできませんし、すべきでもありません。フラグされたインストールは、確認された脅威としてではなく、パッケージを読むきっかけとして扱ってください。

npqはnpm auditやSocketの代替でもありません。これらは補完的な関係にあります。3つのツールはそれぞれ異なる窓口をカバーします:

ツール実行タイミングチェック内容CI対応
npqインストール前公開日時、インストールスクリプト、タイポスクワット、OSV経由の既知CVE(またはSnyk)非対応 — インタラクティブにプロンプト
npm auditインストール後インストール済みパッケージのCVE対応(組み込み)
Socket継続的依存関係グラフの振る舞い分析、マージ後のモニタリング対応(アプリ + CLI)

npqはインストール前のシグナルを検出し、npm auditはすでにディスク上にあるパッケージのCVEを検出し、Socketはマージ後の依存関係グラフの継続的な振る舞いモニタリングを追加します。npqのインストール時ゲートと--ignore-scriptsをデフォルトとして組み合わせ(ライフサイクルスクリプトが本当に必要な依存関係にはLavaMoat allow-scriptsなどのツールを使用)することで、インストール時の攻撃対象領域の大部分を閉じることができます。

まとめ

npmnpq-heroにエイリアス設定し、huskyフックでコミットをゲートすることで、依存関係を取得するすべての場所(ローカルターミナルとコミット時)に同じインストール前監査が適用されます。まずグローバルインストールとシェルエイリアスから始め、次に依存関係マニフェストに触れる際にhuskyフックを組み込みましょう。marshallはヒューリスティックなので、フラグされた内容を読んでください。しかし、postinstallペイロードがすでに実行された後に発見するよりも、警告を読む方がはるかに良いのは言うまでもありません。

よくある質問

プロジェクトがドキュメント化している方法では使用できません。NPQ_DISABLE_AUTO_CONTINUEをtrueに設定するか、--disable-auto-continueを渡すことで15秒の自動続行を削除し、明示的な(y/N)プロンプトを強制できますが、プロンプトは依然として回答を期待します。フラグされたすべてのパッケージを自動的に非ゼロ終了に変換するドキュメント化されたフラグは存在しません。npqの信頼できるユースケースはインタラクティブなものです。npq-heroエイリアスを介したターミナルでの使用と、プロンプトに回答できる人がいるhuskyフックを介したコミット時の使用です。

npqとnpq-heroは一緒にインストールされる2つの別個のバイナリです。npqはnpm installの代わりに実行する明示的な監査コマンドです。npq-heroは完全なnpm互換ラッパーです。run、ci、publishなどすべてのnpmサブコマンドをそのままパススルーし、インストール時のみ傍受して先に監査を実行します。npmを生のnpqバイナリにエイリアスすると、npqが実装していないサブコマンドが動作しなくなるため、READMEではnpq-heroへのエイリアスを推奨しています。

npqはNPQ_PKG_MGR環境変数を通じてpnpmでも動作します。NPQ_PKG_MGRをpnpmに設定すると、監査が通過した後にどのパッケージマネージャーを呼び出すかをnpq-heroに伝えます。NPQ_PKG_MGR=pnpm npq install fastifyのようにコマンドごとに設定することも、alias pnpm='NPQ_PKG_MGR=pnpm npq-hero'のようにシェルエイリアスに組み込んで、すべてのpnpmインストールがnpqのmarshallを経由するようにすることもできます。

両方を使用してください。カバーする窓口が異なるからです。npqはインストール前に実行され、パッケージの公開日時、ライフサイクルスクリプト、タイポスクワット、OSV経由の既知脆弱性データ(設定時はSnyk経由)を検査し、悪意のあるコードがディスクに触れる前に停止します。npm auditはインストール後に実行され、すでにnode_modulesに書き込まれたパッケージのCVEを報告します。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