見出し画像

npm依存関係のサプライチェーン攻撃と、npm v12の大幅セキュリティ強化を徹底解説

〜開発者のための実践対応ガイド〜

はじめに

npmエコシステムはJavaScript開発の基盤ですが、依存関係を通じたサプライチェーン攻撃が深刻化しています。2025年9月には、Chalk/Debugの大規模侵害や自己複製型ワーム「Shai-Hulud」が相次ぎ、合計で週20億ダウンロード規模のパッケージが影響を受けました。

そして2026年6月9日、GitHubがnpm v12で「破壊的変更(breaking changes)」を予告しました。その中核が、`npm install`時のinstallスクリプト実行をデフォルトで無効化するものです。GitHub自身が「npmエコシステム最大のコード実行面(single largest code-execution surface)」と表現する攻撃経路を、デフォルトで塞ぎにいきます。

この記事では、攻撃の実態、npm v12の変更点、影響、具体的な対応手順を、公式情報に基づいてまとめます。依存の多いプロジェクトを運用している方は必見です。


1. npmサプライチェーン攻撃とは?

攻撃者は人気パッケージを狙い、インストール時や利用時に悪意のコードを実行させます。

主な攻撃手法

  • Maintainerアカウント乗っ取り:フィッシングで認証情報を奪取し、悪意あるバージョンを公開する

  • postinstall / preinstallスクリプト悪用:`npm install`時に自動実行されるライフサイクルスクリプトにマルウェアを仕込む(RAT、認証情報窃取、自己拡散ワームなど)

  • Typosquatting / Dependency Confusion:似た名前の偽パッケージや、社内パッケージ名の衝突を突く

  • node-gyp / binding.gyp悪用:ネイティブビルド時の暗黙的なコード実行を悪用する

検証済みの主な事例(2025年9月)

※以下は一次情報・複数のセキュリティベンダーで裏付けの取れた事例のみを掲載しています。

  • Chalk / Debug など18パッケージ侵害(2025年9月8日)
    メンテナ「Qix」氏のアカウントが偽の2FA更新メール(`npmjs.help`ドメイン)によるフィッシングで乗っ取られ、`chalk`(週約2.99億DL)、`debug`(週約4,700万DL)を含む18パッケージにクリプトクリッパー型マルウェアが混入。合計で週20億ダウンロード超の規模。ブラウザ上でWeb3/暗号資産のトランザクション宛先を書き換える挙動でした。悪意あるバージョンは数時間で削除されています。

  • Shai-Hulud ワーム(2025年9月)
    `@ctrl/tinycolor`を起点に発見された自己複製型ワーム。postinstallフックを悪用して、npmトークン・GitHub PAT・クラウドキー(AWS/GCP/Azure)などの認証情報を盗み、盗んだ認証情報でさらに500以上のパッケージへ自己増殖しました。「インストール時スクリプト」が攻撃の核心だった代表例です。

これらの攻撃はインストール時点や利用時点で被害が発生し、CI/CDや開発者PCを汚染し得ます。とりわけ Shai-Hulud のようにライフサイクルスクリプトを足がかりにする手口は、npm v12が狙い撃ちにする攻撃面そのものです。


2. npm v12の変更点(2026年7月リリース予定)

GitHub公式チェンジログ(2026-06-09)に基づく主な変更点です。いずれも「今は自動で走る挙動」を「明示的にオプトインする挙動」へ変えるものです。

  • `allowScripts` がデフォルトでオフ
    → `preinstall` / `install` / `postinstall` スクリプトが、プロジェクトで明示的に許可されない限り自動実行されなくなります。
    ネイティブ`node-gyp`ビルドも対象:`binding.gyp`があり明示的なinstallスクリプトを持たないパッケージでも、npmが暗黙的に`node-gyp rebuild`を実行するためブロックされます。
    → git / file / link 依存の`prepare`スクリプトも同様にブロックされます。

  • `--allow-git` がデフォルトで `none`
    → 直接・推移的を問わず、Git依存が明示許可(`--allow-git`)なしには解決されなくなります。これは、`--ignore-scripts`を付けてもGit依存の`.npmrc`がGit実行ファイルを上書きできてしまうコード実行経路を塞ぐためです。(npm 11.10.0以降で利用可、2026-02-18に予告済み)

  • `--allow-remote` がデフォルトで `none`
    → httpsのtarボールなどリモートURLからの依存解決が、明示許可(`--allow-remote`)なしにはできなくなります。(npm 11.15.0以降で利用可)
    → なお`--allow-file` / `--allow-directory`のデフォルトはv12では変更されません。

これらの変更はnpm 11.16.0以上ですでに警告として確認できるようになっており、アップグレード前に事前準備が可能です。


3. 影響を受けるプロジェクト

  • ネイティブモジュール:`sharp`, `bcrypt`, `canvas`, 各種DBドライバなど(ビルド時にスクリプト/`node-gyp`を使うもの)

  • ツール類:Cypress, Playwright, Puppeteer, Electron, Husky など、postinstallでバイナリ取得やセットアップを行うもの

  • 依存数の多いプロジェクト全般:CLIツールやエージェント系、フロントエンド大規模アプリなど、間接依存が多い環境ほど「保留中スクリプト」が多く出るため要注意です。


4. 今すぐやるべき対応(準備手順)

  1. npmを11.16.0以上にアップグレード

  2. 通常どおり `npm install` を実行 → 表示される警告を確認

  3. 生成されたallowlist(`package.json`に書き込まれます)をGitにコミット

  4. CI/CDでも同じ`package.json`のallowlistが適用されるようにする(`npm ci`推奨)

pnpmユーザーはすでに類似の厳格制御(`onlyBuiltDependencies`によるビルド許可制)があるため、考え方の移行はスムーズです。


5. 追加の防御策(ベストプラクティス)

  • Socket / StepSecurity / Dependabot などでパッケージ・依存を継続監査する

  • `npm audit` とlockfileの厳格なレビューを習慣化する

  • CIでは`--ignore-scripts`やサンドボックス環境を併用する

  • `devDependencies`を分離し、最小権限の依存構成を保つ

  • npmアカウントの2FA強化、Trusted Publishing(信頼された公開)を活用する

  • `min-release-age`の活用:npmは「公開から指定日数未満のバージョンを拒否する」設定を導入済み。公開直後の悪意あるバージョンを掴まされるリスクを下げられます。


おわりに

npm v12は「デフォルトでは信頼しない(secure by default)」方向への大きな一歩です。攻撃が完全になくなるわけではありませんが、blast radius(影響範囲)を大幅に縮小できます。重要なのは、リリース前の今のうちに`npm install`の警告を確認し、信頼できるスクリプトのallowlistを整備しておくことです。

「自分のプロジェクトのどの依存が影響を受けそうか」「allowlist作成を手伝ってほしい」「pnpmとの比較など追加トピックがほしい」といったご要望があれば、ぜひコメントください。


参考

いいなと思ったら応援しよう!

zephel01 サーバー代とコーヒー代になります☕ 役に立ったら応援よろしくお願いします!