本当は怖くない?CVSSスコアに惑わされない脆弱性との付き合い方
レバテック開発部の松浪です。
先日、 multipart/form-data形式のHTTPリクエストを生成できるnpmパッケージ form-data
にCVSSスコア9.4(Critical)の脆弱性が見つかりました。
CVSSスコア9.4(Critical)とあれば、非常に危険!即時対応!と考える方もいるかもしれません。本当にそうでしょうか?
脆弱性対応において重要なのは、スコアの高さだけでなく、その脆弱性が、自分たちのプロダクトで実際に悪用される可能性があるのか? 、悪用された場合にどのような影響があるのか? を判断することです。
たとえスコアが高くても、発動する条件に該当しない、そもそもその機能を使っていない、といったケースでは、即時対応は不要かもしれません。
この記事では、form-data
を例に、脆弱性に関する影響調査の内容について記載しようと思います。
1.脆弱性の詳細を探る
脆弱性を検知したら、まずは脆弱性の内容を知ることから始めます。
脆弱性が発見されたからといってライブラリ全体が危険なわけではありません。
多くの場合、脆弱性はライブラリ内の特定の機能やロジックに存在します。
そこで、修正内容を確認してみると...
今回の form-data
ライブラリの例では、 Math.random()
を使って境界値を生成している getBoundary()
関数内に脆弱性があることがわかります。
脆弱性の詳細を知るには、CVE(共通脆弱性識別子)やGHSA(GitHub Security Advisory)を確認すると良いです。
修正した時のコミットがわかる
どこに脆弱性があったか載っている(場合がある)
2.依存関係を探る
package.jsonに脆弱性のあるライブラリがないから大丈夫、というわけではありません。
多くのアプリケーションでは、推移的依存関係 という形で直接は記載されていないライブラリがインストールされています。
推移的依存関係とは、アプリケーションが直接利用しているライブラリ(例:axios
)が、さらに別のライブラリ(例:coveralls
)に依存し、そのライブラリがさらに別のライブラリ(例:request
)に依存し、最終的に脆弱性のあるライブラリ(例:form-data
)にたどり着く、という間接的な依存関係のことです。
脆弱性管理ツールは、この推移的依存関係の奥深くまで潜って脆弱性を検出するため、package.jsonに記載がなくても警告が出ることがあります。
パッケージマネージャーには、推移的依存関係を知るための便利なコマンドが用意されています。
Yarn の場合
yarn why -R <パッケージ名>
% yarn why -R form-data
└─ my-project@workspace:.
└─ newrelic@npm:12.21.0 (via npm:^12.20.0)
└─ @newrelic/security-agent@npm:2.4.2 (via npm:^2.4.2)
└─ sync-request@npm:6.1.0 (via npm:^6.1.0)
└─ then-request@npm:6.0.2 (via npm:^6.0.0)
└─ form-data@npm:2.5.1 (via npm:^2.2.0)
npm の場合
npm ls --all <パッケージ名>
% npm ls --all form-data
my-project@1.0.0
└─┬ newrelic@12.21.0
└─┬ @newrelic/security-agent@2.4.2
└─┬ sync-request@6.1.0
└─┬ then-request@6.0.2
└── form-data@2.5.1
という具合で、 form-data
に辿り着くまでの推移的依存関係が出力されます。
3.依存関係を読み解き、影響の有無を判断する
依存関係を確認したら、次に「本当に自プロダクトに影響があるのか?」を判断します。
いくつかのパターンでは、「影響を受ける可能性が低い」と判断できる場合があります。
脆弱性のあるロジック(メソッド)を使用していない
脆弱性が見つかってもライブラリ全体が危険なわけではありません。
脆弱性のあるライブラリが本番リリースの資材に含まれていても、そのライブラリ内の脆弱性が存在する特定の関数やロジックを直接的にも間接的にも使用していない場合、自プロダクトに影響を及ぼす可能性は低いと言えます。
ただ、間接的にも使用していないと判断するには、ライブラリのソースコードを詳細に確認する必要があり、判断が難しいこともあります。
次に紹介する2つの条件は、ソースコードを深く読み込まなくてもよいので判断が容易です。
型定義ファイルへの依存関係
@types/
で始まるTypeScriptの型定義ファイル(.d.tsファイル)を介して脆弱なライブラリに依存している場合、自プロダクトに影響を及ぼす可能性は低いと言えます。
型定義ファイルはコンパイル時にのみ使用され、実際のjavaScriptのコードには含まれません。
devDependencies
にあるライブラリの依存関係
Jest
のような開発・テスト用途のライブラリ(devDependencies
に分類されることが多い)が脆弱なライブラリに依存している場合も、自プロダクトに影響を及ぼす可能性は低いと言えます。
本番環境へのデプロイ時には devDependencies
に含まれるライブラリは本番環境の資材には含まれません。
4.脆弱性を修正したバージョンにアップデートする
影響を受ける可能性があると判断できたら、脆弱性を修正したバージョンにライブラリをアップデートします。
CVE-2025-7783 を見ると、脆弱性は以下のバージョンで修正されています。
- 2.x系: 2.5.4以降
- 3.x系: 3.0.4以降
- 4.x系: 4.0.4以降
package.jsonには直接書かれていない推移的依存関係にあるライブラリをアップデートしたい場合どうするか?
パッケージマネージャーには、推移的依存関係にあるライブラリのバージョンを指定するためのフィールドが用意されています。
Yarn の場合
package.jsonの resolutions
というフィールドを利用すれば、推移的依存関係にあるライブラリのバージョンを指定することができます。
{
"resolutions": {
"form-data": "4.0.4" // ★ 修正済みのバージョンを強制
}
}
npm の場合
package.jsonの overrides
というフィールドを利用すれば、推移的依存関係にあるライブラリのバージョンを指定することができます。
{
"overrides": {
"form-data": "4.0.4" // ★ 修正済みのバージョンを強制
}
}
直接使っていないライブラリであっても、そのバージョン変更が予期せぬ副作用を引き起こす可能性があります。
アップデート後は必ず自動テストや動作確認を実施して問題なく動作するか検証しましょう。
まとめ
CVSSスコアは客観的な指標にすぎず、本当に自プロダクトに危険が及ぶかは、依存関係やコードの使用状況を分析して初めて判断できます。
yarn why
や npm list
といったコマンドを駆使すれば、推移的依存関係まで確認することができますので、リスクを見極める際はぜひ、これらのコマンドを活用してみてください。
Discussion