自社の共通UIコンポーネントやAPIクライアントを npm パッケージとして配っている。あるいは、委託先が作ったSDKを社内のプロジェクトが軒並み参照している。この構成自体は珍しくありません。
問題は、その公開が CI に置いたトークン1本で完結している ことです。タグを打てばワークフローが走り、ビルドが通れば公開される。人は誰も間に入りません。効率としては正しい設計ですが、裏を返せば、そのトークンを手に入れた誰かも同じことができます。しかも新しいバージョンは、公開された瞬間から世界中の npm install に配られます。
2026年に相次いだサプライチェーン攻撃の多くは、脆弱性を突いたものではありませんでした。CI/CD から盗んだ公開トークンを使い、正規の手順で汚染版を公開するという形です。ビルドは通っていて、署名も正規で、公開者も正規のアカウント。検知が難しいのは、どこも異常ではないからです。
最後の一歩だけを、人に戻す
npm はこれに対して、公開の直前に人間の承認を挟む仕組みを追加しました。段階公開(staged publishing)で、2026年5月22日から全パッケージで利用できます。
動きはこうです。npm publish の代わりに npm stage publish を実行すると、パッケージはレジストリに載らず、ステージングのキューに入ります。この時点では誰もインストールできません。そのあと、メンテナが2要素認証を通したうえで承認して、初めて公開されます。
操作は次のサブコマンドで完結します。
npm stage publish # ステージングキューに積む(2FA不要・CIから実行できる)
npm stage list # 承認待ちの一覧を見る
npm stage view <stage-id> # 中身(tarball)を確認する
npm stage approve <stage-id> # 2FA を通して公開する
npm stage reject <stage-id> # 破棄する
**npm stage publish は、トークンの種類にかかわらず2FAを求めません。**これが設計上の勘所です。CI は今までどおり自動でビルドして積むところまでを担当し、世に出す判断だけが人の手に残ります。CI を弱くすることなく、盗まれたトークンでできることの上限を「キューに積むこと」まで下げられます。

推奨される構成は「CIは積むだけ」
GitHub 側が示している組み合わせは、OIDC を使った信頼できる公開(trusted publishing)と段階公開の併用です。ワークフローの権限を stage-only に設定すると、npm stage publish は通り、npm publish は拒否されます。
この設定が入って初めて、抜け道がなくなります。段階公開を導入しても、従来の npm publish が使えるまま残っていれば、攻撃者はそちらを使うだけです。承認ゲートは、迂回路を塞いで初めてゲートになります。
同時期に、インストールする側の制御(--allow-* 系のオプション)も追加されています。公開する側と使う側の両方に手が入った形なので、自社がどちら側なのかで見るべき機能が変わります。パッケージを配っていない組織にとっては、後者のほうが直接効きます。
導入前に確認しておくこと
要件は、npm CLI 11.15.0 以降と Node.js 22.14.0 以降です。CI のランナーが古い Node のまま固定されている場合、ここで引っかかります。リリース用ワークフローのバージョン指定を先に確認してください。
いくつか制約もあります。
新規パッケージは段階公開できません。レジストリに既に存在するパッケージが対象です。最初の1回は従来どおり公開する必要があります。
ステージング時に付けたタグは、あとから変更できません。latest で積んだものを next に変えたい場合は、いったん npm stage reject で破棄してから積み直します。タグの付け間違いが起きやすいリリース手順なら、ここは事前に整理しておくほうが混乱が少なくなります。
リリースツールとの相性が出ます。changesets のような自動リリースツールを使っている場合、npm publish を直接呼ぶ実装になっていると段階公開の経路に乗りません。対応状況を確認してから移行時期を決めてください。
運用で形骸化させないために
承認ゲートは、入れた翌月から形骸化が始まります。防ぐ側の手当てを最初に決めておきます。
承認者を1人にしないでください。リリースが承認者の在席に依存すると、不在の日に緊急パッチが出せません。「承認者が休みなので今回は直接公開した」が1回でも通ると、その経路が常用されます。
承認時に何を見るかを決めておいてください。npm stage view で中身を確認できる仕組みがあっても、見る基準がなければクリックするだけの作業になります。差分のファイル数、想定していないファイルの混入、依存関係の追加、postinstall スクリプトの有無。この程度でも、決めてあるかどうかで意味が変わります。インストール時に走るスクリプトが何をしうるかはnpm install で任意コードが走るという前提で扱っています。
承認までの待ち時間を、リリース計画に織り込んでください。「即座に出せる」前提でスケジュールを組んだままだと、承認が律速になった瞬間にゲートを外す圧力がかかります。
使う側にとって何が変わるか
自社がパッケージを配っていない場合、この機能は直接は関係ありません。ただし、依存している主要パッケージが段階公開を採用しているかどうかは、リスクの見積もりに影響します。採用しているパッケージは、トークン漏洩による汚染版の公開が起きにくくなっています。
とはいえ、これは公開側の対策です。使う側の防御は別に必要で、依存を取り込むまでに時間差を置く運用が引き続き有効です。この考え方はDependabot の cooldown が既定になったで整理しました。汚染版が公開されてから撤回されるまでの数時間を、そのまま踏まないための仕組みです。
委託先に聞くこと
自社向けのパッケージを外部に作らせている、あるいは保守を委託している場合、次を確認しておくと状況が把握できます。
- そのパッケージの公開は、CIから自動で行われているか。人が手元から公開しているなら、また別のリスクの話になります
- 公開に使っているトークンは、いつ発行されたものか。長期のまま放置されたトークンが残っている状態については委託先のビルド環境、まだ長期トークンで動いていませんかで扱いました
- 段階公開または同等の承認ゲートを入れる予定はあるか。入れない判断でも構いませんが、理由が「知らなかった」なのか「運用上難しい」なのかで、こちらの受け止め方は変わります
- 承認できる人は何人いるか。1人なら、その人が抜けたときの手順も併せて確認します
これは委託先を疑う質問ではなく、攻撃が成立する経路を双方で把握しておくための確認です。実際にサプライチェーン経由の事故が起きたとき、いちばん時間を食うのは「どこから入られたか分からない」状態です。攻撃全体の広がりは2026年のサプライチェーン攻撃にまとめています。
次にやること
自社が npm レジストリに公開しているパッケージを1つ選び、そのリリースワークフローを開いてください。確認するのは、npm publish を実行しているステップに、人の承認が一切挟まっていないかどうかです。挟まっていなければ、そのトークンが漏れた時点で汚染版が公開されます。
公開しているパッケージが無い場合は、依存関係のうち社内製・委託先製のものを数えてください。それが実質的に自社のサプライチェーンの範囲です。
リリースフローへの承認ゲートの組み込みや、委託先を含めたビルド環境の権限設計については、グリームハブの開発・AI・自動化のご相談で承っています。開発体制やリリース頻度によって現実的な落としどころは変わるため、個別にご相談ください。お問い合わせからどうぞ。
Sources
- Staged publishing and new install-time controls for npm — GitHub Changelog(2026-05-22)
- Staged publishing for npm packages — npm Docs
- npm-stage — npm Docs
- npm Staged Publishing Available, Adding a Human Approval Step Before Packages Go Live — InfoQ
- npm Adds 2FA-Gated Publishing and Package Install Controls Against Supply Chain Attacks — The Hacker News