CIに保存したnpmトークンが漏れたとき、攻撃者が新しいパッケージ版をそのまま公開できる。そんな権限を、本当に自動化へ渡し続ける必要があるでしょうか。

GitHubは2026年9月18日、npmのgranular access tokenでRead and write(stage only)を選べるようになったと発表しました。CIはパッケージをステージング領域へ提出できますが、そのトークンによる直接公開は拒否されます。公開には保守担当者のレビューと2要素認証(2FA)が入ります。GitHub Changelog

<style> .st-summary,.st-note,.st-flow{padding:1.2rem;margin:1.5rem 0;border:1px solid #cbd8e7;border-radius:16px;background:#eef5ff;color:#162e47}.st-summary p:last-child,.st-note p:last-child{margin-bottom:0}.st-cards,.st-pipeline{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,205px),1fr));gap:12px;margin:1.5rem 0}.st-card,.st-step{padding:1.1rem;border:1px solid #cbd8e7;border-radius:14px;background:#fff;color:#162e47}.st-step strong{display:block;font-size:1.6rem;color:#12667b}.st-step.safe{background:#e8f8ef;border-color:#91cfaa}.st-step.stop{background:#fff0ec;border-color:#e4a392}.st-card h3{margin-top:0}.st-table{overflow-x:auto;margin:1.5rem 0}.st-table table{border-collapse:collapse;width:100%;min-width:650px}.st-table th,.st-table td{padding:.85rem;border:1px solid #cbd8e7;text-align:left}.st-table th{background:#e7effa;color:#162e47}.st-note{background:#fff6e6;border-left:5px solid #9a5c00}.st-flow ol{padding-left:1.3rem}.st-flow li{margin:.7rem 0} </style>

① stage-onlyトークンで、CIから公開前レビューまでを自動化できます。

② 公開は2FAを使う人の承認へ分離。トークン漏えい時の直接公開リスクを下げます。

③ 書き込み権限がゼロになるわけではないため、対象パッケージと保管範囲は絞ります。

新しい境界:作る人と公開する人を分ける

npmのstaged publishingは、npm publishで即時公開する代わりに、npm stage publishで版をステージング領域へ送る仕組みです。保守担当者は内容を確認し、CLIまたはnpmjs.comで2FAを使って明示承認します。npm公式ドキュメント

1. CI

ビルド・試験・パッケージ作成

2. Stage

トークンでレビュー待ちへ提出

3. 人が確認

内容をレビューし2FAで承認

4. 公開

承認後にレジストリへ反映

stage-onlyトークンを使ってnpm publishを直接実行すると、npmが拒否します。自動化側に侵害が起きても、新しい版を即時公開する権限を持たせないことが今回の重要な変化です。

「stage only」は読み取り専用ではありません。 公式発表によると、dist-tagの移動や版の非推奨化など、ほかのパッケージ書き込み権限は残ります。通常の書き込みトークンと同じように保護し、対象パッケージを必要最小限にしてください。[残る権限の注意](https://github.blog/changelog/2026-09-18-stage-only-npm-tokens-for-safer-automation/)

3つの公開方式をどう選ぶ?

最優先で検討したいのは、長期間使うnpmトークンをCIからなくせるtrusted publishing(OIDC)です。npmは、承認したワークフローと信頼関係を結び、実行ごとの短命な認証情報を使う仕組みと説明しています。npm:trusted publishing

一方、対応CIや実行環境などの事情ですぐOIDCへ移れない場合に、stage-onlyトークンは直接公開できる長期トークンより権限を狭める移行経路になります。staged publishingはOIDCと組み合わせることもできます。

公開方式の権限境界
方式CIの認証公開前の人の承認主な検討点
直接公開トークン長期トークン構成次第でなし漏えい時に直接公開され得る。
stage-onlyトークン長期トークンだが直接公開不可2FAで必要ほかの書き込み権限は残る。
OIDC+直接公開ワークフロー固有の短命認証公開方式による対応プロバイダーとワークフロー設定を確認。
OIDC+staged publishingワークフロー固有の短命認証2FAで必要トークン削減とレビューを両立。

この表は「どれが常に正解か」ではなく、認証情報の寿命と公開承認を分けて比較するための整理です。人の承認を追加すると公開までの時間や当番設計も変わるため、緊急修正版の経路も試験します。

導入条件:対応バージョンと既存パッケージ

npm Docsで確認できる主な前提は次の通りです。

npm CLI

11.15.0以上

Node.js

22.14.0以上

対象

npm registryに既に存在するパッケージ

保守担当

publish権限と2FAが必要

新規パッケージの初回版はステージできません。また、stage-onlyトークンの作成手順と、staged publishing自体の前提を両方満たす必要があります。前提条件

GitHub Actionsの変更例

次は概念を示す最小例です。本記事制作時にnpmへ提出・公開していません。実在パッケージへそのまま適用せず、ブランチ保護、環境承認、対象パッケージ、スクリプトの副作用を確認してください。

name: Stage npm package
on:
  workflow_dispatch:

permissions:
  contents: read

jobs:
  stage:
    runs-on: ubuntu-24.04
    environment: npm-staging
    timeout-minutes: 15
    steps:
      - uses: actions/checkout@v6
        with:
          persist-credentials: false
      - uses: actions/setup-node@v7
        with:
          node-version: '22.14.0'
          registry-url: 'https://registry.npmjs.org'
      - run: npm ci
      - run: npm test
      - run: npm stage publish
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_STAGE_TOKEN }}

ここで指定した22.14.0は最低条件を見せるための例で、利用中ライブラリのサポート期間や組織標準に合わせて選びます。Actionのバージョン、ランナーOS、Node.js、npm CLIは別の更新対象です。必要なnpm CLI版が同梱されているかを実行時に確認し、足りなければ信頼できる方法で明示導入してください。

移行テストで本物の公開用トークンを使わないでください。 対象を限定したstage-onlyトークンと検証用パッケージを使い、`npm publish`が拒否されること、承認前は公開されないこと、2FA承認後だけ公開されることを確認します。

安全な移行の6ステップ

  1. 公開経路を棚卸し。 CI、手動公開、bot、複数レジストリ、残っているトークンを特定する。
  2. OIDC適合性を先に確認。 対応CIならtrusted publishingを第一候補にし、レビューが必要ならstaged publishingを組み合わせる。
  3. 対象を絞ったトークンを作る。 stage-onlyを選び、必要な既存パッケージだけに限定する。保存先は承認付き環境も検討する。
  4. 検証用パッケージで試す。 成果物、provenance、タグ、インストール、拒否動作、承認手順を記録する。
  5. 運用を切り替える。 `npm publish`を`npm stage publish`へ変更し、レビュー担当と緊急時の当番を決める。
  6. 旧トークンを失効。 成功確認後に直接公開できる認証情報を削除し、利用履歴と残存箇所を再点検する。

開発・保守・運用・企業への影響

開発者は、ステージされたtarballをダウンロードし、想定外のファイルやビルド生成物が入っていないか確認できます。保守担当は、版番号・変更履歴・テスト結果・provenanceを承認条件として明文化します。

運用担当は、承認待ちの滞留、却下理由、緊急公開の所要時間を観測します。企業では「CI担当者がレビュー担当者も兼ねる」状態を避けるだけでなく、不在時の代替承認者と2FA復旧手順も決めます。

リスクと限界

stage-onlyトークンは、CIで任意コードが実行される問題や、ビルド成果物の改ざんを解決するものではありません。攻撃者がステージした版を、人が十分に確認せず承認するリスクも残ります。依存Actionの固定、権限縮小、保護された環境、成果物の照合など、ほかの防御と組み合わせます。

今回の機能は既存トークンを自動変更しないオプトインです。GitHubの発表では、npmはbypass-2FAトークンによる直接公開を2027年1月に廃止する目標も示しています。これは本稿確認時点の目標であり、実施状況は移行時に公式情報を再確認してください。移行に関する発表

今後見るべきこと

OIDC対応環境の拡大、staged publishingの監査情報、組織向けポリシー、承認の自動通知を注視します。まずは「長期トークンをなくせるか」、難しければ「直接公開権限だけでも外せるか」の順で検討すると、目的が明確になります。

今日の一歩は、npmへ直接公開できるトークンがどこに残っているかを棚卸しすること。 新しいトークンを追加する前に、古い強い権限を確実に撤去する計画を作りましょう。

最終確認日:2026年9月19日(日本時間)。機能・条件・日程は公式資料、ワークフロー例と移行手順は本稿の提案です。

参照元

Previous Post Next Post