依存パッケージの脆弱性 — あなたのコードは1行も変わっていないのに、穴が開く

あなたのアプリは package.json の数十本と、それらが依存する数百〜数千本のパッケージの上に乗っている。その1本に穴が見つかる、または乗っ取られると、あなたのアプリにも穴が開く。2025年9月〜2026年5月の npm 攻撃「Shai-Hulud」では 1,300超のバージョンが乗っ取られ、install しただけで開発者のトークンが盗まれた。依存は「入れたら終わり」ではなく「借りている」。月1回 npm audit、ignore-scripts、lockfile、Dependabot。AI に audit を読ませる頼み方と確かめ方。

動画で見る

結論から

あなたのアプリは、あなたが書いた(AI が書いた)コードだけでは動いていません。package.json に書かれた数十本のパッケージと、それらがさらに依存する数百〜数千本のパッケージの上に乗っています。その1本に穴が見つかる、または乗っ取られると、あなたのアプリも穴が開きます。2025年9月から2026年5月にかけて npm を襲った「Shai-Hulud」と呼ばれる攻撃では、keyv flat-cache など広く使われるパッケージを含む 1,300以上のバージョンが乗っ取られ、インストールしただけで開発者の認証情報(GitHub・npm・クラウドのトークン)が盗まれる仕組みでした。

この記事で伝えたいのは、この一点だけです。依存パッケージは「入れたら終わり」ではなく「借りている」。借り物は定期的に点検し(`npm audit`)、赤い文字が出たら「何が・どこで・直せるか」を AI に読ませる。 そして、install のたびに勝手にスクリプトが走らない設定にする。AI は「動く」までは面倒を見ますが、その後の点検は頼まれない限りやりません。

  • 何が起きるか:①よく使われるパッケージに脆弱性が見つかる(既知の穴)。②パッケージの作者アカウントが乗っ取られ、悪意あるバージョンが公開される(サプライチェーン攻撃)。どちらも、あなたのコードは1行も変わっていないのに、穴が開く
  • なぜ:依存は「一度入れたら見ない」ものになりがち。AI が生成したプロジェクトは、依存が多く、古い版に固定されていることも多い
  • 直す:npm audit を月1回。ignore-scripts=true で install 時の自動スクリプトを止める。ロックファイル(package-lock.json)をコミットする。GitHub の Dependabot を有効にする
  • 確かめる:npm audit を実行して、critical / high の件数を見る。ゼロでなければ、AI に「この結果を読んで、直せるものは直して、直せないものは理由を説明して」

動画版(約2分半)は本文の上に埋み込んであります。

① 何が起きるのか:自分のコードは1行も変わっていないのに

例として、AI で作った予約アプリがあるとします。package.json には 30本ほどのパッケージ。node_modules を数えると、それらが依存する分も含めて 1,200本入っています。あなたが名前を知っているのは、そのうち5本くらいでしょう。

この1,200本のどれか1本に、2つのことが起きます。

① 既知の脆弱性が見つかる。 「このバージョンの画像処理ライブラリには、細工した画像ファイルでサーバーを乗っ取れる穴がある」のような報告が、日々公開されます(CVE という番号が付きます)。あなたのアプリがその版を使っていれば、あなたのアプリにも穴があります。npm audit は、この「既知の穴」の一覧と、あなたの依存を照合するコマンドです。

② 乗っ取られる(サプライチェーン攻撃)。 パッケージの作者の npm アカウントが盗まれ、悪意あるバージョンが公開される。あなたが npm install や npm update をした瞬間、それが入ります。2025年9月の Shai-Hulud(第1波)は、感染したパッケージを install すると、開発者の GitHub・npm・AWS のトークンを盗み、そのトークンで開発者が管理する他のパッケージにも自分を複製する「ワーム」でした。11月の第2波、2026年5月の第3波と続き、累計で 1,300 以上のバージョン、月間 20億ダウンロード相当のパッケージが影響を受けました。

どちらの場合も、あなたのコードは1行も変わっていません。変わったのは、借り物の中身です。

依存パッケージは借り物。月1回 npm audit、install 時の自動実行を止める

② なぜ起きるのか:依存は「入れたら見ない」

原因は、依存パッケージが「一度入れたら見返さない」ものになりがちなことです。動いている限り、package.json を開く理由がありません。

AI で作ったプロジェクトは、この傾向が強くなります。依存が多い(AI は「便利だから」と1機能ごとに1パッケージ足す)。版が古いまま固定される(AI が学習した時点の版を書く)。`install` 時に走るスクリプト(postinstall)を気にしない。そして、動作確認は「機能が動くか」だけで、「依存に穴がないか」は見ない。

Shai-Hulud が広がった理由の1つは、npm install のときに自動で走る preinstall / postinstall スクリプトです。パッケージを入れただけで、任意のコードが実行される。これは npm の正規の仕組みですが、攻撃者にとっては「install してもらえれば勝ち」を意味します。

AI はどう書くか。 「動く」までは面倒を見ます。npm audit の赤い文字が出ても、頼まれなければ読みません。「エラーじゃないから」です。そして、ignore-scripts や Dependabot のような「点検の仕組み」は、機能ではないので提案しません。

③ どう直すのか:AIに「audit を読ませる」「install を守る」

以下をそのまま AI ツールに貼ってください。

「このプロジェクトで npm audit(Python なら pip-audit)を実行し、結果を読んで、①critical と high の脆弱性を一覧にし、②npm audit fix で直せるものは直し、③直せないもの(メジャーバージョンアップが必要・修正版が無い)は、それぞれ影響と対応案を説明してください。次に、プロジェクト直下の .npmrc に ignore-scripts=true を追加し、install 時にスクリプトが自動実行されないようにしてください(必要なパッケージがあれば個別に教えてください)。package-lock.json がコミットされていることを確認し、されていなければ追加してください。最後に、GitHub の Dependabot(.github/dependabot.yml)を有効にする設定を追加してください。」

ポイントは、「直せないものは理由を説明して」。AI に npm audit fix --force を勝手に走らせると、アプリが壊れることがあります。直せるものと直せないものを分けます。

④ 直ったかを確かめる:月1回、npm audit

  • ターミナルで `npm audit` を実行し、末尾の X vulnerabilities (Y critical, Z high, …) を見る。critical / high がゼロなら ◯。ゼロでなければ③のプロンプト
  • `.npmrc` に `ignore-scripts=true` があるか。無ければ追加(一部のパッケージはビルドにスクリプトが要るので、AI に確認)
  • `package-lock.json` が Git に入っているか。.gitignore に入っていたら外す
  • GitHub のリポジトリで Security → Dependabot が有効か。有効なら、脆弱性が見つかったときに自動で PR が来る
  • カレンダーに「月1回 `npm audit`」 を入れる。AI にも「毎月1日に audit 結果をまとめて」と定期タスクを頼めるなら頼む
  • 分からなければ、AIに「npm audit --audit-level=high が0件で終わることを CI で確認する設定を書いて」

自分で直せないとき:エンジニアに送る一文

「npm audit で critical / high が出ています。修正と、直せないものの影響評価をお願いします。あわせて ignore-scripts・lockfile のコミット・Dependabot の設定も確認してください。」

よくある質問

`npm audit` の警告が100件以上出ます。全部直すのですか。

まず critical と high だけを見ます。moderate / low の多くは、開発時にしか使わないツール(テスト・ビルド)のもので、本番の穴ではないことが多いです。AI に「本番で動くコードに影響するものだけ」と絞らせてください。

`npm audit fix --force` を実行すればいいですか。

やめてください。--force はメジャーバージョンを跨いで更新するので、アプリが動かなくなることがあります。まず --force 無しで、直らないものは個別に判断します。

スロップスクワッティング(前の記事)と何が違うのですか。

前の記事は「存在しない名前の偽物」、今回は「本物のパッケージに穴が見つかる/本物が乗っ取られる」です。防ぎ方も違い、前者は install 前の目視、後者は install 後の定期点検と ignore-scripts です。

この穴が塞がれば、依存パッケージは安全ですか。

「既知の穴」と「install 時の自動実行」は防げます。「まだ誰も知らない穴」は防げないので、被害を小さくする設計(本番と開発の分離、最小権限。→ AI エージェントの記事)と組み合わせます。