Dependabotの脆弱性アラートを片付けようとして npm audit fix --force を実行しかけたところ、Next.js 16を9.3.3にダウングレードするという提案が出てきました。この記事では、なぜこうなるのか、そして --forceを使わずに脆弱性を直す方法をまとめます。
この記事の時系列について
「発生した状況」以降は 2026年7月28日時点の出来事です。その後、Next.js 本体にも重大な脆弱性が公表され、状況が変わりました。2026年10月時点の対応は「現在の状況」の節を先に読んでください。記事中のバージョン番号をそのまま使わないでください。
結論:--forceの提案は、そのときの公開バージョン次第でダウングレードにもアップグレードにもなる
先に結論です。
npm audit fix --forceは、脆弱性を消すためならメジャーバージョンのダウングレードも行います。実行前に、何をインストールしようとしているのか必ず読んでください。- 脆弱性対応の基本は親パッケージ(今回は Next.js)を修正版に上げることです。
- 親パッケージがまだ修正版を出していないときだけ、
package.jsonのoverridesで依存パッケージを修正版に固定します。
実際、同じ状態で同じコマンドを実行しても、2026年7月には「9.3.3 へのダウングレード」、2026年10月には「16.3.8 へのアップグレード」が提案されました。提案の中身は、その時点で公開されているバージョンによって変わります。だから毎回読む必要があります。
以下で、7月に起きたことと原因、そして現在の状況を順に説明します。
発生した状況:DependabotのHIGHが増えていた(2026年7月)
運用中のNext.jsサイトで、GitHubのDependabotアラートが29件(うち HIGH が多数) に増えていました。まずは定石どおり、--forceなしで修正を試しました。
npm audit fix
これでNext.js本体は16.2.10から16.2.12に上がり、当時公表されていた Next.js自体の脆弱性は解消されました。ところが、本番で使う依存だけを見ると、まだHIGHが残っていました。
npm audit --omit=dev
| パッケージ | 深刻度 | 経路 |
|---|---|---|
postcss |
HIGH | nextが内部で使用 |
sharp |
HIGH | nextのoptional依存 |
uuid |
moderate | 別ライブラリの奥深く |
環境
- Next.js 16.2 系(App Router)
- npm10系
- 実行環境:Dockerコンテナ
- 依存管理:Dependabot(GitHub)
--forceが提案してきた内容
残った脆弱性について、npmは次のように案内してきました。
postcss <=8.5.17
Severity: high
fix available via `npm audit fix --force`
Will install next@9.3.3, which is a breaking change
node_modules/next/node_modules/postcss
「next@9.3.3をインストールする(破壊的変更)」と書かれています。使っていたのはNext.js 16です。実行すればApp Routerもろとも動かなくなります。
メッセージを読まずに実行していたら、ビルドが通らなくなるところでした。
なぜこうなるのか:脆弱なのはNext.js本体ではない
問題のpostcssは、Next.jsが内部でバージョンを固定している依存でした。next@16.2.12 の package.json では、postcss が範囲指定ではなく8.4.31の完全一致で指定されています。そのため、npm audit fixでは上げられません。
npmはこの状況で「脆弱なpostcssを含まないNext.jsのバージョン」を探します。古いnext@9.3.3はpostcssにそもそも依存していないため、条件を満たしてしまいました。npmの計算としては正しいのですが、アプリが動くかどうかは考慮されていません。
当時の対応:overridesで依存パッケージを固定する
当時は、postcssとsharpの修正版を使うNext.jsがまだ公開されていませんでした。そこでnpm 8.3 以降で使えるoverridesを使い、依存ツリーの奥にあるパッケージのバージョンを強制的に指定しました。
{
"overrides": {
"sharp": "^0.35.4",
"postcss": "^8.5.24"
}
}
当時の設定は
"sharp": "^0.35.3"でしたが、その後sharpの脆弱性の対象が0.35.4 未満に広がりました。今overridesを書くなら、下限を0.35.4以上にしてください。^0.35.3のままだと、ロックファイルに0.35.3が残っている環境では脆弱なままです。
変更したらnpm installでロックファイルを作り直します。
npm install
確認方法
1. 依存ツリーで古いバージョンが残っていないか
npm ls sharp
├─┬ next@16.2.12
│ └── sharp@0.35.3 deduped
└── sharp@0.35.3
deduped は「上の階層に入っている同じパッケージを共有している」という意味です。Next.js の配下に古いバージョンが別に入っていないことを確認します(表示は2026年7月当時のものです)。
2. 本番で使う依存の脆弱性が消えたか
npm audit --omit=dev
--omit=devを付けると、テストやビルドツールなど開発時だけ使う依存を除外して、本番に影響する脆弱性だけを確認できます。当時はこれでHIGHが0件になりました。
3. ビルドとテスト、実際の処理が動くか
npx tsc --noEmit
npm test
npm run build
overridesはパッケージ作者が想定していないバージョンを強制するので、ビルドとテストに加えて、そのパッケージを使う処理を実際に動かして確認してください。今回は sharpを使う画像変換スクリプトも実行して確認しました。
現在の状況(2026年10月時点)
記事と同じ状態(Next.js 16.2.12)を作り、2026年10月に npm audit --omit=dev を実行し直しました。結果は大きく変わっていました。
1. Next.js 16.2.12そのものにcriticalの脆弱性がある
その後、Next.jsにリモートでコードを実行される脆弱性(RCE)が 3件 公表されました。
| 脆弱性 | 深刻度 | 対象バージョン |
|---|---|---|
| GHSA-p293-qw3h-jr36 | critical | 16.0.0 以上 16.3.3未満 |
| GHSA-2xp9-vwfh-vxw4 | critical | 16.0.0 以上 16.3.3未満 |
| GHSA-vcvr-r3jv-pc5j | critical | 16.2.0 以上 16.3.6未満 |
16.2.12で止めるのは危険です。少なくとも16.3.6以上に上げる必要があります。
2. --forceの提案がアップグレードに変わった
同じ操作をすると、今度は次の提案になります。
Will install next@16.3.8, which is outside the stated dependency range
ダウングレードではなく、最新版へのアップグレードです。
3. Next.jsを上げるだけで全部直る
next@16.3.8 は、修正済みのpostcss(8.5.23)と sharp(^0.35.4)を自分で指定しています。実際に next@16.3.8で確認したところ、overrides なしで脆弱性は 0件でした。
npm install next@16
npm audit --omit=dev
# found 0 vulnerabilities
今この記事を読んでいる方は、overridesを書く前にNext.jsを最新版に上げてください。すでにoverridesを書いている場合は、Next.jsを上げたあとで外し、npm lsで同じバージョンが入っていることを確認します。
おまけ:暗黙の依存に気づいた
sharpを調べている途中で、もう一つ問題が見つかりました。画像を変換するスクリプトがsharpをimportしているのに、package.jsonに sharpが書かれていなかったのです。
Next.jsのoptional依存として入っていたsharpに、たまたま相乗りして動いていただけでした。Next.js側の都合でsharpが外れたら、スクリプトが突然動かなくなります。
{
"devDependencies": {
"sharp": "^0.35.4"
}
}
「動いているから大丈夫」ではなく、コードでimportしているものは必ずpackage.jsonに書く。脆弱性対応は、こうした見落としを見つける機会にもなります。
よくある質問
Q. overridesを書くと、親パッケージが壊れませんか?
A. 壊れる可能性があります。今回のsharpがまさにその例でした。
next@16.2.12がsharpに指定していたのは^0.34.5です。0.xのパッケージでは、キャレット(^)は2桁目を固定します。つまり^0.34.5は「0.34.5 以上 0.35.0 未満」という意味で、0.35系はこの範囲の外です。
npmは0.xの2桁目が上がることを「互換性が壊れる変更」として扱います。今回の上書きは、Next.js が想定していないバージョンを入れていたことになります。だからこそ、ビルドとテストだけでなく、sharpを使う処理を実際に動かして確認しました。overridesは便利ですが、親パッケージの想定を外れる可能性があるという前提で使ってください。
Q. overridesはいつ外せばいいですか?
A. 親パッケージが修正版を使うようになったら外せます。今回はnext@16.3.8が修正済みのpostcssとsharpを指定しているので、Next.jsを上げれば外せる状態です。外したあとは npm lsで同じバージョンが入っていることを確認してください。
Q. 開発用の依存の脆弱性は放置していいですか?
A. 本番に影響しないため優先度は下がりますが、放置でよいわけではありません。今回は本番分を先に片付け、開発用の依存は別の作業として扱いました。依存の都合ですぐ上げられないもの(例:ESLint のメジャー更新が必要なもの)は、課題として記録しておくのがおすすめです。
Q. 一度対応したら、しばらく見なくて大丈夫ですか?
A. 大丈夫ではありません。今回、7月に HIGH を 0件にした版(16.2.12)に、約2か月のうちに critical の脆弱性が見つかりました。脆弱性の状況は、コードを何も変えていなくても変わります。Dependabot のアラートは定期的に確認してください。
まとめ
npm audit fix --forceの提案は、その時点で公開されているバージョン次第で、ダウングレードにもアップグレードにもなる。実行前に必ず読む- 脆弱性対応の基本は親パッケージを修正版に上げること
- 親パッケージがまだ修正版を出していないときだけ、
overridesで依存を固定する。下限は脆弱性が修正されたバージョン以上にする overridesは親パッケージの想定外のバージョンを入れることがある。ビルド・テストに加えて、実際の処理で動作を確認する- 2026年10月時点では、Next.js を最新版(16.3.6 以上)に上げれば、
overridesなしで今回の脆弱性はすべて直る
同じように --force の提案に戸惑った方の参考になれば幸いです。
参考
- npm-audit – npm Docs
- package.json(overrides)– npm Docs
- npm-ls – npm Docs
- About semantic versioning – npm Docs
- GHSA-p293-qw3h-jr36 – GitHub Advisory Database
- GHSA-2xp9-vwfh-vxw4 – GitHub Advisory Database
- GHSA-vcvr-r3jv-pc5j – GitHub Advisory Database
