ASP.NET アプリを開発していると、jQuery や Bootstrap、Newtonsoft.Json などの「脆弱なパッケージ」警告が Visual Studio 2022 のビルドでいつまでも残り、原因が分からず時間を溶かしてしまうことがあります。本記事では、NuGet で最新版に更新しても警告が消えないときに、何から順番に確認すればよいのかを、チェックリスト形式で詳しく解説します。
ASP.NET で「脆弱なパッケージ」警告が残り続ける典型パターン
まず、よくある相談内容を整理します。
- ASP.NET(.NET Framework / .NET 6+ いずれも)で開発中
- NuGet で jQuery / Bootstrap / Newtonsoft.Json などを最新版に更新済み
- 不要な参照は外した「つもり」なのに、ビルドすると「脆弱なパッケージがあります」という警告が消えない
- Visual Studio 2022 を使用しているが、右クリックに「未使用の参照の削除」が出てこない
この状況の多くは、次のいずれか(あるいは複数)が原因です。
- ビルドキャッシュやソリューションキャッシュに古い依存関係が残っている
- トランジティブ依存(間接参照)として古いバージョンがまだ使われている
- 静的ファイル(
wwwrootやScriptsフォルダ)の jQuery / Bootstrap 本体をスキャナが検出している - 同じソリューション内の別プロジェクト・別ターゲットが古いパッケージを参照している
- Visual Studio の表示と実際の依存解決結果にずれがある
これらを順番に潰していくことで、「どこから警告が出ているのか」が明確になり、やるべきことがはっきりします。
まず試す「最短ルート」:これだけで直るケースも多い
質問スレッドでも採用されていた結論が、以下のシンプルな手順です。
- Visual Studio を一度終了する
- すべてのプロジェクトの
bin/とobj/フォルダを削除(旧スタイルならpackages/も削除) - ソリューションを再度開く
- ソリューションの「クリーン」を実行
- NuGet パッケージの復元を実行
- ソリューション全体を再ビルド
これだけで、「脆弱なパッケージ」警告がきれいさっぱり消えることも少なくありません。まずはここから試すのがおすすめです。
どの種類の「脆弱性警告」なのかを切り分ける
次に重要なのは、「どのレイヤーの警告なのか」を見極めることです。同じ jQuery でも、.NET のパッケージ監査の警告なのか、静的ファイルとしてのスキャン結果なのかで対処が完全に変わります。
| 警告の種類 | 主な出どころ | 見え方の例 | 主な対処 |
|---|---|---|---|
| .NET(NuGet)パッケージの脆弱性 | NU19xx 系の警告など | ビルド時に「脆弱な依存関係があります」など | NuGet 更新・トランジティブ依存のピン留め |
| 静的ファイルの脆弱性 | セキュリティスキャナ、SAST、DevSecOps ツールなど | レポートで jquery-1.12.4.js の CVE が列挙される | 古い .js/.css ファイルの削除・置き換え |
| 外部 CDN 利用に対する警告 | セキュリティレビュー、コードレビュー | https://cdn.../jquery/latest.js のような指定 | バージョン固定・SRI 付与 |
特にフロントエンドの静的ファイルに対するスキャン結果は、「NuGet で更新しても全然消えない」という典型的な混乱ポイントです。NuGet と静的ファイルは別物なので、両方を意識的に整理する必要があります。
ソリューションのキャッシュを一掃して整合性を取り直す
最短ルートで触れたとおり、キャッシュの破棄は最初にやっておきたい基本対応です。ここでは、もう少し丁寧に手順を整理します。
ビルド成果物の削除
- Visual Studio を終了する
- 各プロジェクト配下の
bin/フォルダを削除 - 各プロジェクト配下の
obj/フォルダを削除 - 旧スタイル(
packages.configあり)の場合はソリューション直下のpackages/フォルダも削除
その後、ソリューションを開き直してから、
- ソリューションの「クリーン」
- NuGet パッケージの復元
- ソリューションの「ビルド」
を順番に実行します。これにより、古い DLL や project.assets.json に紐づいた情報がリセットされ、最新の依存関係でビルドし直されます。
.vs フォルダの削除で VS 内部キャッシュもリセット
Visual Studio の「参照ツリー」がおかしく見える場合は、ソリューションを閉じた状態で以下も試すとよいです。
- ソリューションと同じ階層にある
.vsフォルダを削除 - ソリューションを再度開く
これで「実際には削除されている NuGet 参照が、ソリューション エクスプローラーにはまだ残って見える」といった違和感が解消されることがあります。
トランジティブ依存を洗い出し、「ピン留め」する
NuGet 上で直接参照しているパッケージをすべて更新しても、別のパッケージ経由で古い版が参照されていると、脆弱性警告は残ったままになります。これが「トランジティブ依存」の落とし穴です。
SDK スタイル プロジェクトなら dotnet list package --vulnerable
<Project Sdk="Microsoft.NET.Sdk.Web"> などの SDK スタイル プロジェクトであれば、ターミナル(PowerShell / コマンド プロンプト)から以下を実行するだけで、どのパッケージが問題かを一覧できます。
dotnet list package --vulnerable --include-transitive
このコマンドのポイントは、--include-transitive オプションです。これにより、直接参照していない「間接参照」のパッケージも含めて、脆弱性を持つものがすべて表示されます。
出力結果を見ながら、
- どのパッケージが古い jQuery / Bootstrap / Newtonsoft.Json を引っ張ってきているのか
- 最新の安全なバージョンはいくつか
を確認し、必要に応じて次のいずれかの方法で対処します。
- 依存元パッケージ(例:古い WebAPI/SignalR)自体を更新する
- どうしても依存元を更新できない場合、
<PackageReference>を明示的に追加し、安全なバージョンを「ピン留め」する
Directory.Packages.props でバージョンを統一管理
複数プロジェクトを抱えるソリューションでは、中央でバージョンを管理することで「プロジェクトAだけ古い」「テストプロジェクトだけ古い」といったブレを防げます。
代表的なのが Directory.Packages.props を用いた「Central Package Management」です。ソリューション直下などにこのファイルを置き、
<Project>
<ItemGroup>
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="jQuery" Version="3.7.1" />
</ItemGroup>
</Project>
といった形でバージョンを一元管理しておくと、どのプロジェクトでも同じバージョンが自動的に使われます。
複数プロジェクト・マルチターゲットを横断チェック
ソリューション内に Web 本体プロジェクトのほか、テストやツール用のプロジェクトが入っている場合、それらが古いパッケージを抱えたままになっていることがあります。
特に、
- ユニットテスト プロジェクト
- 移行途中の古いユーティリティ プロジェクト
- マルチターゲット(
net48;net6.0など)しているプロジェクト
は要注意です。片方のターゲットでだけ古いバージョンを参照している、というパターンもあります。
| チェック対象 | 見るポイント | 対処の例 |
|---|---|---|
| テストプロジェクト | Newtonsoft.Json / jQuery などのバージョン | 本体プロジェクトと同じバージョンに揃える |
| 古いユーティリティ | packages.config の中身 | 不要な参照を削除し、必要なら更新 |
| マルチターゲット | Condition 付き参照の有無 | ターゲットごとにバージョン差がないか確認 |
静的ファイルの「取り残し」:wwwroot / Scripts / Content を整理する
NuGet 側をいくら綺麗にしても、wwwroot や Scripts フォルダの中に古い jQuery / Bootstrap の .js / .css が残っていると、セキュリティスキャナや SAST ツールは容赦なく検出します。
よくあるパターン
- 昔のバージョンをバックアップのつもりで
jquery-1.9.1.old.jsのようにリネームして残している Scriptsとwwwroot/libの両方に jQuery があり、一方が古い- LibMan 導入前の手作業コピーがそのまま残っている
このような「亡霊ファイル」は、思い切って削除するか、そもそも配置方法を統一する必要があります。
フロントエンド資産は「1つの仕組み」に統一する
おすすめは、以下のうちいずれか 1 つに統一することです。
- LibMan(
libman.json)でwwwroot/libに展開する - npm / Webpack / Vite などでバンドルした成果物だけを
wwwrootに置く - CDN 利用に切り替え、ローカルコピーは置かない
CDN を使う場合は、
- バージョンを固定する(
latest.jsなどは避ける) - Subresource Integrity(SRI)属性を付与する
ことで、セキュリティレビューを通しやすくなります。
旧式 ASP.NET と最新 .NET での違い:「未使用の参照の削除」が出ない理由
質問にもあった「未使用の参照の削除(Unused references)」メニューは、実はどのプロジェクトでも表示されるわけではありません。この機能は基本的に C# の SDK スタイル プロジェクト向けであり、従来の ASP.NET(.NET Framework + packages.config)では出てきません。
| 項目 | SDK スタイル(.NET 5+ / ASP.NET Core) | 非 SDK スタイル(従来 ASP.NET / .NET Framework) |
|---|---|---|
| 参照管理 | <PackageReference> 中心 | packages.config + <Reference> |
| 「未使用の参照の削除」 | コンテキストメニューに表示 | 表示されない |
| 推奨される整理方法 | 右クリックで未使用参照を削除、dotnet コマンドで監査 | NuGet UI でアンインストール、packages.config / .csproj の手動整理 |
従来 ASP.NET アプリで警告を消したい場合は、以下のように手動で整理する必要があります。
- NuGet パッケージ マネージャの UI から不要なパッケージをアンインストール
packages.configで該当パッケージの行が残っていないか確認し、あれば削除.csprojの<Reference Include="..." />や<PackageReference>を確認し、不要なものを手動で削除- その後
Update-Package -reinstall(パッケージマネージャーコンソール)で整合性を取り直す
Visual Studio の表示と実体のズレをチェックするテクニック
「NuGet では最新版になっているのに、どこかから古いバージョンを参照しているようだ」というときは、ビルド生成物側の情報を直接確認すると早いです。
obj/project.assets.json を直接見る
SDK スタイル プロジェクトであれば、
obj/project.assets.json
に最終的な依存解決結果が JSON 形式で書かれています。このファイルを開き、
"Newtonsoft.Json/12.0.3"のような文字列が残っていないか- jQuery や Bootstrap の古いバージョンがどのパッケージから参照されているか
を検索すると、依存元を特定しやすくなります。
警告 ID(例:NU190x)とセットでメモを取る
ビルド時に出ている警告 ID(NU1901 など)と、「どのプロジェクトで」「どのパッケージ名・バージョンに対して」出ているかをメモしておくと、調査対象がぐっと絞り込めます。
| 項目 | 例 |
|---|---|
| 警告 ID | NU1901 |
| プロジェクト名 | MyApp.Web |
| パッケージ名 | Newtonsoft.Json |
| 検出バージョン | 12.0.1 |
| 期待するバージョン | 13.0.3 |
この情報が揃えば、「テストプロジェクトだけ更新されていない」「トランジティブ依存で古いバージョンが残っている」といった仮説を立てやすくなります。
どうしても消えない警告を一時的に抑制する方法(最終手段)
業務の都合上、いますぐには依存元のパッケージを更新できない場合や、既知の低リスク脆弱性を一時的に許容せざるを得ない場合もあります。そのようなケースでは、警告自体を一時的に抑制することも技術的には可能です。
- SDK スタイル:
.csprojの<NoWarn>に特定のNU19xxを追加する - 監査対象を「直接依存のみ」に絞る設定にする
ただし、これはあくまで現実的な「最後の手段」です。根本解決はあくまで、
- パッケージを更新する
- 不要な参照を削除する
- バージョンを統一する
ことにあります。抑制した警告は、必ず技術的負債として管理し、定期的な見直しを行いましょう。
セキュリティ観点から見た「最低限ここだけは守りたいポイント」
ASP.NET アプリの脆弱性対応として、特に重要なポイントを最後に整理しておきます。
CDN 利用時は SRI + 固定バージョン
https://cdn.../jquery/latest.jsのような可変 URL は避け、明示的なバージョン番号を指定するintegrity属性とcrossorigin属性を付与し、SRI を有効化する
JSON シリアライザは可能なら System.Text.Json へ移行
新規開発や大規模リファクタリングのタイミングでは、
- ASP.NET Core では標準の
System.Text.Jsonを優先 - どうしても Newtonsoft.Json が必要な箇所だけに限定する
といった方針にすることで、依存パッケージを減らし、将来の脆弱性対応コストを抑えられます。
jQuery / Bootstrap の供給源を一本化する
- 「NuGet でも入れているし、昔の静的ファイルも残っているし、CDN も一部で使っている」という状態を解消する
- 「このプロジェクトでは ここからだけ jQuery / Bootstrap を提供する」というルールを決める
供給源が散らばっているほど、「どこを更新すれば安全なのか」が分かりにくくなります。一本化は、セキュリティだけでなく保守性の面でも非常に重要です。
まとめ:警告 ID と「どこから来ているか」を特定できれば解決まで一直線
ASP.NET で jQuery / Bootstrap / Newtonsoft.Json などの「脆弱なパッケージ」警告がビルドから消えない場合、多くのケースでは次の流れで解決できます。
- Visual Studio を再起動し、
bin/・obj/(必要ならpackages/・.vs/)を削除してクリーン & 再ビルド - SDK スタイルなら
dotnet list package --vulnerable --include-transitiveでトランジティブ依存を含めて洗い出す - 複数プロジェクトやマルチターゲット環境で、どこか一つだけ古いパッケージが残っていないか確認する
wwwroot/やScripts/などに置き去りになった古い静的ファイルを整理し、フロントエンド資産の管理方法を一本化する- どうしても解決できない場合のみ、警告 ID をピンポイントで抑制する
ポイントは、「どの警告 ID が」「どのプロジェクトで」「どのパッケージ・どのファイルに対して」出ているのかを冷静に切り分けることです。一度そこまで分解できれば、あとは更新・削除・統一といった具体的な作業に落とし込むだけです。
本記事のチェックリストを手元に置いて順番に潰していけば、「何を変更しても警告だけは消えない」というモヤモヤ状態から抜け出し、ASP.NET アプリの依存関係を安全かつクリーンな状態に保てるようになるはずです。

コメント