npm audit を実行すると critical や high が並びますが、上から順に直すのが正しいとは限りません。npm audit が並べるのは脆弱性そのものの重大度で、あなたのコードがその関数を呼んでいるか、外から入力が届くか、いま悪用されているかは出力に含まれません。逆に、重大な脆弱性が公開されているのに何も出ないこともあります。
連載「事故から逆算するWebセキュリティ」の第14回は、依存関係の既知の脆弱性を毎週どう仕分けて直すかを、古い lodash と minimist で警告を再現しながら整理します。攻撃者がパッケージそのものを乗っ取る手口は サプライチェーン攻撃とは|手口・防御ツール比較・npm 12の新機構まで実践解説 で扱いました。この記事は、公開済みの脆弱性に対する日々の判断を扱います。
LIST VS TRIAGE読み方を変える
重大度の順ではなく、届くか・狙われているかで並べ直す
npm audit の出力
CVSS の重大度で並ぶ
- critical 2件・high 1件
- 直接か推移的かは --json で
- 悪用の実績や到達性は出ない
仕分けたあと
5つのシグナルで順番を決める
- KEV 掲載・EPSS が高いものを先に
- 自分のコードが呼ぶか(到達性)
- 本番で動き、外から入力が届くか
30秒でわかる(2026年10月17日時点)
- ・npm audit の順番は重大度の順。到達性・露出・悪用の実績は自分で足す
- ・
npm audit --jsonのisDirectとfixAvailableで、直接依存か推移的依存か、何を上げれば直るかが分かる - ・優先度を上げるのは KEV 掲載・EPSS の高さ・本番で外から届くこと。開発用だけで呼ばない関数なら後回しにできる
- ・推移的依存は
overridesで上書きできる(minimist 0.0.8 → 0.2.4 で0件を実測)。親が直ったら外す - ・0件は安全の証明ではない。Next.js の10月の3件は、10月17日時点でも npm audit に出なかった
npm audit の警告と、先に直すべき脆弱性は一致しない
まず、警告が積み上がる理由を時系列で見ます。2020年8月13日(UTC)に公開された lodash 4.17.20 を固定したままにすると、その後の公表のたびに警告が増えていきます。
| 公表日(UTC・GitHub Advisory Database) | 内容 | 修正版 |
|---|---|---|
| 2021年5月6日 | CVE-2021-23337:_.template のコマンドインジェクション(high) |
4.17.21 |
| 2026年1月21日 | CVE-2025-13465:_.unset・_.omit のプロトタイプ汚染(moderate) |
4.17.23 |
| 2026年4月1日 | CVE-2026-4800:_.template の imports 経由のコード注入(high)ほか1件 |
4.18.0 |
公表日と修正版は、github/advisory-database の OSV 形式のレコードを raw.githubusercontent.com から取得して確認しました。lodash の各版の公開日は npm レジストリの記録で確かめています(4.18.1 は2026年4月1日 UTC 公開)。
どれも _.template や _.unset といった特定の関数の問題です。その関数を使っていなければ、同じ high でも危険の大きさは変わります。
もう一つの問題は、出ないことです。2026年10月14日に公開された Next.js の脆弱性3件について、npm audit が使う照会先(npm のドキュメントにある /-/npm/v1/security/advisories/bulk)に next 16.4.0 と 15.5.27 を10月17日に問い合わせたところ、返ったアドバイザリは0件でした。3件の GHSA は github/advisory-database の reviewed 配下にも見つかりませんでした。同じ照会で sharp 0.34.5 には high が3件返り、その1件は CVE-2026-96889 の原因になった librsvg のものです。経緯と確認コマンドは Next.js CVE-2026-96889|SVG経由のRCEと10月の3件、sharpが古いまま残る落とし穴 にまとめました。
警告は多すぎることも、足りないこともあります。だから、出てきた警告に自分で順番を付け直す作業が要ります。
npm audit の結果を読む:直接依存と推移的依存を見分ける
手元で再現します。lodash 4.17.20 を直接依存に、minimist 0.0.8 を mkdirp 0.5.1 経由の推移的依存(依存の依存)として入れました。実行環境は Node.js 22.22.0・npm 10.9.4 です。
npm init -y
npm install --save-exact [email protected] [email protected]
npm audit # 3 vulnerabilities (1 high, 2 critical) / 終了コード 1
npm audit --json | jq -r '.vulnerabilities[] | [.name, .severity, (if .isDirect then "direct" else "transitive" end), (.fixAvailable | if type=="object" then "\(.name)@\(.version)" else tostring end)] | @tsv'
npm explain minimist # minimist@"0.0.8" from [email protected] ← mkdirp@"0.5.1" from the root project
--json の出力を表にすると次のとおりです。
| パッケージ | 重大度 | 依存の種類 | 直す手段(fixAvailable) | 主な CVE |
|---|---|---|---|---|
| lodash 4.17.20 | high | 直接 | lodash 4.18.1 | CVE-2021-23337 ほか4件 |
| minimist 0.0.8 | critical | 推移的 | 親の mkdirp 0.5.6 | CVE-2021-44906(CVSS 9.8) |
| mkdirp 0.5.1 | critical | 直接 | mkdirp 0.5.6 | 自身の脆弱性ではない |
読み方の要点は3つあります。
・mkdirp の critical は、mkdirp 自身の欠陥ではありません。npm のドキュメントが「metavulnerability」と呼ぶもので、脆弱な minimist にしか解決できない版だから付く印です
・npm audit fix --force は「宣言した範囲の外の版を入れる」と表示しました。範囲の外へ上げる更新なので、内容を読まずに実行しないでください
・npm audit の JSON には GHSA の URL・CVSS・CWE は入りますが、CVE 番号・EPSS・KEV は入りません。CVE 番号は GHSA のレコードの aliases で確かめました
優先順位を決める5つのシグナル
仕分けに使う情報と、それぞれが順番をどう動かすかを表にしました。
| シグナル | どこで調べるか | 優先度への効き方 |
|---|---|---|
| KEV 掲載 | CISA の Known Exploited Vulnerabilities カタログ | 載っていれば実際に悪用されている。最優先 |
| EPSS | FIRST の EPSS。GitHub のアドバイザリにも表示 | 今後30日に悪用される確率の推定。高ければ前倒し |
| 到達性 | 自分のコードの呼び出しを検索、OSV-Scanner の呼び出し解析 | 脆弱な関数を呼ばないなら下げられる。誤判定の影響は大きい |
| 露出 | 本番か開発用か、外部の入力が届くか | 開発用だけで外部入力が無ければ下げる |
| 修正の有無 | fixAvailable、アドバイザリの修正版 |
修正版があれば更新。無ければ緩和策を選ぶ(次の H2) |
TWO AXESどれから直すか
届く×狙われているは今日、どちらも弱いものは記録して次の更新へ
到達性・露出(低い → 高い)→
今週の定例で直す
本番で呼んでいるが、悪用の兆候はまだ弱い
今日直す
KEV 掲載か EPSS が高く、外から届く
記録して次の更新へ
開発用だけ・呼ばない関数・兆候も弱い
届かないかを確かめて前倒し
到達性の判断を誤ると最悪の組み合わせになる
悪用の兆候(KEV・EPSS)弱い → 強い →
KEV は、CISA が GitHub で公開しているミラー(cisagov/kev-data)を取得して照合しました。2026年10月16日版(1,748件)に、今回の lodash と minimist の5件、CVE-2026-96889 は載っていませんでした。JavaScript まわりでは、React Server Components の CVE-2025-55182 が2025年12月5日に追加されており、ランサムウェアでの利用も「Known」とされています。
今回の脆弱性の EPSS の値は未検証です。GitHub のドキュメントによると、GitHub Advisory Database は CVE のあるアドバイザリに FIRST の EPSS を毎日同期して表示し、Dependabot のアラートは epss-percentage:>=0.10 のような条件で絞り込めます。百分率は「今後30日に悪用される確率」、パーセンタイルは「それより低いスコアの脆弱性の割合」です。
到達性は、脆弱な関数を自分のコードが呼んでいるかを検索して見積もります。CVE-2021-23337 と CVE-2026-4800 は _.template の問題なので、次の検索をかけます。
# _.template / lodash.template / lodash/template を呼んでいる箇所(出なければ到達性は低い見込み)
grep -rnE "\.template\(|lodash/template" --include=*.js --include=*.ts src/
_.get だけを使う src/ では何も出ず(終了コード1)、import template from "lodash/template" を置いたファイルを足すと1行出ました(終了コード0)。ただし、この検索は自分のコードしか見ません。分割代入で取り出した呼び出しや、別の依存の中からの呼び出しは拾えません。何も出なくても、脆弱な関数に到達しないとは限らない点に注意してください。OSV-Scanner の README には、呼び出し解析で脆弱な関数が使われているかを判定する機能が書かれていますが、今回は試していません。
対策:更新・overrides・修正版が無いときの手当て
直し方は、上から順に検討します。
・直接依存を上げる。lodash は npm install --save-exact [email protected] で直りました
・推移的依存は親を上げる。mkdirp を 0.5.6 にすると minimist は 1.2.8 になり、minimist の警告は消えました(メジャー更新の判断は mkdirp の作者が済ませています)
・親を上げられないときは overrides で上書きする。npm のドキュメントは、既知の脆弱性がある依存の版を置き換える用途として overrides を挙げています
minimist の脆弱性には 0.x 系の修正版(0.2.4)もあります。親の mkdirp 0.5.1 は "minimist": "0.0.8" と固定しているので、ルートの package.json で上書きします。
# package.json に追記: "overrides": { "minimist": "^0.2.4" }
npm install --save-exact [email protected]
npm ls minimist lodash # [email protected] └─ [email protected] overridden
npm audit # found 0 vulnerabilities / 終了コード 0
npm ls に overridden と出ます。lockfile では mkdirp の宣言が 0.0.8 のまま残り、実体だけ 0.2.4 になっていました。overrides には次の制約があります。
・ルートの package.json だけが効く。依存先や workspaces の overrides は無視される
・直接依存しているパッケージは、依存の指定と同じでないと上書きできない。$foo の形で直接依存の指定を参照できる
・親が想定していない版を入れる。テストを通し、上書きした理由と外す条件を残す
Next.js の例では、15系を 15.5.28 に上げても lockfile の sharp 0.34.5 が残りました。この場合は overrides より先に npm update sharp で宣言範囲の中の 0.35.5 へ上げる方が素直です(当サイトの10月16日の実測)。
修正版が無いときは、OWASP Top 10:2025 の A03 にある順番が使えます。代わりのパッケージへの移行を考え、それもできなければ仮想パッチ(WAF などで攻撃の入力を検知・遮断する)を置きます。
| 手当て | 例 | 注意 |
|---|---|---|
| 使っていない依存を外す | 移行後に残った依存を削除する | 0件にする一番確かな方法 |
| 該当機能を止める | SVG の読み込みを止める(sharp の回避策は sharp.block()) |
機能が欠ける。止めた設定を記録する |
| 入口で止める | WAF のルール、入力の検証 | 迂回される前提で、修正版が出たら更新する |
| 自分でパッチを当てる | フォークを npm: や Git URL で overrides に指定 |
上流に追従する手間を引き受ける |
影響範囲の判断を誤ると、どの手当ても空振りします。到達性を理由に見送るときは、検索した範囲と日付を残してください。
小さなチームの週次ルーティンと、npm audit の警告疲れを防ぐ方法
専任者のいないチームでは、毎日ではなく週1回の定例に寄せ、KEV に載ったものだけ割り込みで当日に対応するのが続けやすい形です。OWASP Top 10:2025 の A03 は、パッチ適用が月次や四半期の作業になっている環境では、数日から数か月の不要な露出が生まれると書いています。
WEEKLY ROUTINE週1回の定例
小さなチームは週1回の仕分けと、KEV 掲載時の割り込みで回す
週1回
KEVは当日
- 警告を集める
- 5つで仕分ける
- 更新か上書き
- テストして出す
- 見送りを記録
1回の定例でやることは5つです。
・集める:npm audit --json と Dependabot のアラートを1か所に出す
・仕分ける:前の H2 の5つのシグナルで「今日・今週・記録」に分ける
・直す:親の更新を先に、無理なら overrides を使う
・出す:テストを通してから本番へ。自動更新の PR をそのまま取り込まない(Renovate・Dependabotの自動PRがマルウェアを運ぶ:違いの比較と今すぐ確認すべき安全設定)
・記録する:見送った警告に、理由と次に見直す日を書く
警告疲れは、毎回同じ警告を読み直すことから生まれます。減らす手段は道具の側にあります。
| 手段 | 効き方 | 確認した出典 |
|---|---|---|
npm audit --omit=dev |
開発用の依存を照会から外す | npm のドキュメント |
npm audit --audit-level=high |
CI を止める重大度の下限を決める(終了コードが変わる) | npm のドキュメント |
| Dependabot のプリセットルール | 開発用依存の影響の小さい警告を自動で閉じる。公開リポジトリは既定で有効、非公開は設定で有効化 | GitHub Docs |
scope:runtime・relationship:direct |
本番の依存・直接依存の警告だけを表示する | GitHub Docs |
ただし、開発用の依存を外すと、ビルドや CI の中で動くパッケージの警告も見えなくなります。開発用でも、CI の秘密情報に触れるツールは本番と同じ扱いにしてください。
参照ソース
・npm Docs — npm-audit(npm/cli)(bulk の照会先・metavulnerability・終了コード・–force)
・npm Docs — package.json の overrides(npm/cli)
・GitHub Advisory Database(github/advisory-database)(GHSA-35jh-r3h4-6jhm・GHSA-xvch-5gv4-984h・GHSA-r5fr-rjxr-66jc ほかのレコード)
・OSV Schema(introduced・fixed・last_affected の範囲表現)
・GitHub Docs — Prioritizing Dependabot alerts using metrics
・GitHub Docs — GitHub Advisory Database(EPSS scores)
・GitHub Docs — Dependabot auto-triage rules
・CISA Known Exploited Vulnerabilities Catalog(cisagov/kev-data)(2026年10月16日版で照合)
・OWASP Top 10:2025 — A03 Software Supply Chain Failures
・OSV-Scanner README(google/osv-scanner)(呼び出し解析。本記事では未実行)





