
npm v12 がインストールスクリプトを既定オフに - サプライチェーン攻撃時代の破壊的変更とCI移行
Web脆弱性対策の定番教科書。
設計段階から守る実践指南書。
publish権限を鍵で守る物理MFA。
当サイトは Amazon.co.jp を宣伝しリンクすることで紹介料を得る手段を提供する、Amazonアソシエイト・プログラムの参加者です。価格・在庫はリンク先の最新情報をご確認ください。
axios・TanStack と、npm サプライチェーン攻撃の事件を追ってきました。これらに共通していたのは、npm install した瞬間に走る postinstall 系スクリプトが攻撃の起点になるという構造です。pnpm 10 の防御設定でも触れたとおり、パッケージマネージャ側で「入れた瞬間にやられる」を止める流れが加速していました。
そしてついに、npm 本体が同じ方向へ舵を切りました。npm v12 は、依存パッケージのインストールスクリプトを既定でオフにします。npm v12.0.0 は 2026年7月8日にリリースされ、安定版パッチの v12.0.1 が7月10日に続きました(出典: npm/cli releases)。この破壊的変更は 2026年6月9日に GitHub の公式 Changelog で予告されていたものです(出典: GitHub Changelog)。
この記事では、3つの破壊的変更、CI が壊れる仕組み、approve-scripts を使った承認ワークフロー、そして2FAバイパストークンの段階的無効化と trusted publishing への移行までを、実務目線で整理します。
npm v12とは何か - 「暗黙の信頼」からの決別
これまでの npm は、依存パッケージに含まれる preinstall / install / postinstall スクリプトを、インストール時に何の確認もなく自動実行してきました。ネイティブモジュールのビルド(node-gyp)などに必要な仕組みですが、同時に攻撃者にとって最も手軽な実行経路でもありました。汚染された依存を1つ引き込むだけで、開発者や CI の環境で任意コードが走ってしまう。これが「暗黙の信頼」の代償です。
npm v12 は、この前提を反転させます。依存パッケージのスクリプトは明示的に許可したものだけが実行され、それ以外は既定でスキップされます。pnpm 10 が先に採用した「デフォルトで止めて、必要なものだけ承認する」設計に、npm 本体が追いついた形です。
3つの破壊的変更
npm v12 の破壊的変更は、大きく3つあります。いずれも「明示的な許可がなければリスクのある解決・実行を行わない」という同じ思想に基づいています。
変更1: allowScripts が既定オフ
最も影響が大きいのがこれです。依存パッケージの preinstall / install / postinstall スクリプトは、明示的な許可がない限り実行されなくなりました。
対象はいわゆる postinstall だけではありません。node-gyp によるネイティブビルドや、git 依存・file 依存・link 依存で走る prepare スクリプトも同じくブロックされます。つまり、これまでインストール時に自動でビルドが走っていたパッケージは、v12 では何もせずスキップされる可能性があります。
変更2: --allow-git が既定 none
--allow-git の既定値が none になりました。git 依存(package.json に GitHub URL などを直接書いたもの、および推移的に含まれるもの)は、明示的な許可がないと解決されません。
これは単なる利便性の変更ではなく、脆弱性を塞ぐための変更です。従来、.npmrc で Git 実行ファイルのパスを差し替えることで、--ignore-scripts を設定していても任意コードを実行できてしまう抜け道がありました。git 依存の解決を既定で止めることで、この経路を封じます。
なお、このフラグ自体は npm v12 でいきなり登場したわけではなく、11.10 から 11.15 系にかけて先行して段階導入されていました。導入バージョンについては公式 Changelog と Socket の記述に食い違いがあるため、ここでは幅を持たせて扱います。
変更3: --allow-remote が既定 none
--allow-remote の既定値も none になりました。HTTPS tarball など、リモート URL を直接指した依存(直接・推移的とも)は、明示的な許可がないと解決されません。レジストリを経由しない任意 URL からのコード取り込みを既定で止める狙いです。
一方で、--allow-file と --allow-directory は既定の変更がありません。ローカルの file 依存・directory 依存はこれまでどおり解決されます。
なぜ今か - Shai-Hulud / axios が突いた postinstall の穴
これほど大きな破壊的変更に踏み切った背景には、ここ1年で連続したサプライチェーン攻撃があります。いずれも postinstall を悪用したものです。
- Shai-Hulud(2025年9月): postinstall 経由で自己増殖するワームが、500を超えるパッケージを汚染しました(
@ctrl/tinycolorなど)。 - Shai-Hulud 2.0(2025年11月): 796の npm パッケージがバックドア化されました。
- Mini Shai-Hulud(2026年5月): 170を超える npm および PyPI のパッケージへ拡散しました。
- axios 乗っ取り(2026年3月): 週間およそ1億ダウンロードのパッケージが標的になりました(詳細はaxiosの記事)。
出典: Palo Alto Unit 42, Aikido。
自己増殖するワームが半年で数百から数千のパッケージへ広がる状況では、「利用者が個別に注意する」という運用はもう限界です。npm がデフォルトの挙動そのものを安全側へ倒したのは、この構造的な圧力への回答だと言えます。
「ソフトスキップ」の挙動とCIでの落とし穴
ここで注意したいのが、v12 の既定挙動がハードエラーではない点です。未承認のスクリプトはスキップされ警告が出るだけで、インストール自体は成功します。これを「ソフトスキップ」と呼びます(出典: Socket)。
一見やさしい挙動ですが、CI では逆に落とし穴になります。ネイティブビルドが必要なパッケージのスクリプトが黙ってスキップされたまま npm install が成功扱いになると、ビルド済みバイナリが存在しないのに次のステップへ進んでしまうからです。結果として、後続のテストや実行時に「モジュールが見つからない」「ネイティブアドオンがロードできない」といった、原因のわかりにくいエラーで CI が壊れます。インストールのログに出た警告を見落とすと、追跡が難しくなります。
WARNING
「npm install は成功しているのにアプリが動かない」という症状が v12 移行後に出たら、まずインストール時の「スクリプトをスキップした」警告を疑ってください。ソフトスキップは失敗を隠すため、成功ステータスを鵜呑みにできません。
strict-allow-scripts でハード失敗に
CI では、このソフトスキップをハード失敗に変換しておくのが安全です。strict-allow-scripts を有効にすると、未承認スクリプトのスキップがそのままインストールの失敗になります。
strict-allow-scripts=trueこうしておけば、「知らないうちに必要なビルドがスキップされていた」状態を、後続ではなくインストールの時点で検知して止められます。承認漏れをレビューのタイミングで気づけるようになるわけです。
実践: approve-scripts での承認ワークフローと package.json 管理
必要なスクリプトは、明示的に承認して動かします。npm v12 には承認用のコマンドが用意されています。
# ブロックされているスクリプトを確認し、信頼するものを承認する
npm approve-scripts
# 特定のパッケージのスクリプト実行を拒否する
npm deny-scriptsnpm approve-scripts を実行すると、既定でブロックされている対象の一覧が表示され、信頼するパッケージを承認できます。逆に「これは絶対に走らせない」を明示したいときは npm deny-scripts を使います(出典: Aikido)。
重要なのは、承認した許可リストが package.json に書き込まれる点です。この許可リストは必ず Git にコミットしてください。コミットしておけば、どの依存にスクリプト実行を許したかがレビュー対象になり、CI や他メンバーの環境でも同じ承認状態が再現されます。pnpm 10 の onlyBuiltDependencies と同じ「許可リスト方式」で、新しく増えた依存が勝手にスクリプトを走らせることはありません。
CI移行チェックリスト
v12 への移行は、いきなり本番 CI で v12 を使うのではなく、事前準備を挟むのが安全です。npm 11.16.0 以降には、v12 の挙動を先取りして警告を出す仕組みがあります。これを使って移行します。
- ローカルまたは検証環境で npm を 11.16.0 以降に上げる。
- 通常どおり
npm installを走らせ、「スクリプトをスキップした」警告を確認する。どの依存がスクリプト実行を必要としているかを洗い出す。 - 洗い出した信頼できるパッケージを
npm approve-scriptsで承認する。 - 更新された
package.json(許可リスト)を Git にコミットする。 - CI の
.npmrcにstrict-allow-scripts=trueを設定し、承認漏れがハード失敗になるようにする。 - この状態で npm v12 に上げ、CI が通ることを確認する。
NOTE
事前準備の肝は、v12 に上げる前に許可リストを確定させてコミットしておくことです。ここを飛ばして v12 に上げると、必要なビルドがまとめてスキップされ、原因調査から始める羽目になります。
なお、npm v12 が対応する Node.js のバージョン範囲は ^22.22.2 || ^24.15.0 || >=26.0.0 です。移行前に、CI や本番のランタイムがこの範囲に収まっているかも確認しておきましょう。v12 は Node 24 / 26 LTS へのバックポートも Node リリースチームで検討中ですが、これは未確定です(出典: Socket)。
2FAバイパストークンの段階的無効化
npm v12 のリリースと並行して、npm 側では公開(publish)に使うトークンの締め付けも進みます。対象は、2FA を回避できる設定になっている Granular Access Token(GAT)です。
フェーズ1は 2026年8月上旬に開始します。該当トークンから、次の操作ができなくなります。
- トークンの作成・削除
- パスワード・メールアドレス・2FA 設定の変更
- パッケージアクセスやメンテナーの変更
- trusted publishing 設定の編集
- org / team の管理
フェーズ2は 2027年1月頃を予定しています。ここでは、これらのトークンからの直接 publish 権限そのものが剥奪され、private パッケージの読み取りと、2FA 承認を要するステージ公開のみが可能になります(出典: The Hacker News, Socket)。
長寿命の publish トークンを CI に置いている運用は、フェーズ2の時点で publish できなくなります。移行の猶予は限られているので、8月のフェーズ1が始まる前に、自分のプロジェクトが該当トークンに依存していないかを棚卸ししておくべきです。
trusted publishing(OIDC) への移行という本命
では、トークンの代わりに何を使うのか。GitHub が推奨しているのは、長寿命の publish トークンをやめ、trusted publishing(OIDC)または人間の承認を挟むステージ公開へ移行することです(出典: GitHub Changelog)。
trusted publishing は、GitHub Actions などの CI ワークフローと npm レジストリを OIDC で暗号的に紐づける仕組みです。ワークフローの実行そのものが身元の証明になるため、盗まれて悪用される長寿命トークンが存在しません。実際、axios 事件では、正規リリースが OIDC で公開されていた一方、攻撃者は盗んだトークンで手動公開して OIDC を回避しました。トークンという「持ち出せる鍵」を排除することが、この種の攻撃への根本的な対策になります。
publish 権限を人間の手で守る場合は、物理的な MFA デバイスを併用すると強度が上がります。フィッシング耐性のあるハードウェアキーで publish 操作を保護しておけば、認証情報が漏れても公開そのものを止められます。
まとめ - 今日やるべきこと
- npm v12 は依存パッケージの
preinstall/install/postinstallスクリプトを既定でオフにする。node-gyp ビルドや git/file/link 依存のprepareも対象。 --allow-gitと--allow-remoteの既定がnoneになり、git 依存・リモート URL 依存は明示許可がないと解決されない。- 既定挙動はソフトスキップ(インストールは成功)。CI では
strict-allow-scripts=trueでハード失敗に変えておく。 - 必要なスクリプトは
npm approve-scriptsで承認し、package.jsonの許可リストをコミットする。 - 移行はまず npm 11.16.0 以降で警告を確認し、許可リストを確定してから v12 へ上げる。
- 2FA バイパス設定の GAT は 8月にフェーズ1、2027年1月頃にフェーズ2で publish 権限が段階的に無効化される。trusted publishing(OIDC)への移行を今から進める。
今日できる最初の一歩は、ローカルの npm を 11.16.0 以降に上げて npm install を1回走らせ、スキップされたスクリプトの警告を確認することです。自分のプロジェクトがどの依存のスクリプト実行に頼っているかを把握するところから始めてください。
参考リンク
- npm/cli Releases(v12.0.0 / v12.0.1)
- Upcoming breaking changes for npm v12 - GitHub Changelog
- npm 12 disables install scripts by default - Socket
- npm v12 blocks postinstall - Aikido
- npm 12 Disables Install Scripts by Default - The Hacker News
- npm supply chain attack analysis - Palo Alto Unit 42
- axios 乗っ取り事件(当ブログ)
- TanStack 乗っ取り事件(当ブログ)
- pnpm 10 のサプライチェーン防御(当ブログ)
- React2Shell の実攻撃事例(当ブログ)


