🔐

npm パッケージ公開を OIDC 認証(Trusted Publishers)へ移行した

に公開

何が起きたか?

2025 年 12 月、npm のセキュリティロードマップに基づき Classic Token が全廃された影響で、GitHub Actions の公開ワークフローが停止しました。

これを受け、従来のトークン管理(Granular / Classic)を廃止し、
より安全でメンテナンスフリーな OIDC 認証(Trusted Publishers) へ移行しました。

OIDC 認証(Trusted Publishers)とは?

従来の方式では、npm に公開するため「パスワード」にあたるトークンを GitHub に保存し、それを使い回していました。

OIDC 認証では、トークンを保存する代わりに「身分証明」の仕組みを使います。
GitHub Actions が npm に対して「このリポジトリの、このワークフローから公開しています」と証明し、npm がそれを確認して公開を許可します。
発行されるトークンは使い捨てで、公開が終われば無効になります。

経緯:トークン選定の迷走

1. Granular Token の課題

当初は、セキュリティ面で推奨されていた Granular Access Token を採用していました。
しかし、有効期限が最大 90 日(以前は最長 1 年)と短く、期限切れのたびに CI が失敗し、手動更新が発生するという運用負荷の高い状態でした。
npmjs.com でのトークン管理は、一人のユーザに紐づいているため更新作業の属人性が高く、運用負荷を減らす方法を探しました。

2. Classic Token (Automation) へ移行と廃止

当時の npm 公式ドキュメント には、
Automation: Suitable for CI/CD workflows.」と記載がありました。
これに従い、運用負荷を抑えるために Classic Token(Automation)へ移行しました。

しかし、npm はサプライチェーン攻撃(トークン漏洩によるマルウェア混入など)への対策としてセキュリティ強化のロードマップを発表。
2025 年 12 月 9 日以降、既存の Classic Token はすべて無効化されました。

時期 出来事 影響 参考
2025年9月 セキュリティ強化発表 Classic Token の新規作成停止 Strengthening npm security
2025年11月 Classic Token 作成停止 新規作成が不可に Classic token creation disabled
2025年12月 Classic Token 全廃 既存トークンがすべて無効化 Classic tokens revoked

3. OIDC 認証(Trusted Publishers)への移行

手動更新による運用負荷と、シークレット(静的なトークン)を保持するリスクを解消するため、現在は npm でも推奨されている OIDC 認証(Trusted Publishers)を採用しました。

OIDC 認証には、従来のトークンベース認証と比較して以下の優位性があります。

  • Secretレス認証: 静的な認証情報の保存を排除し、サプライチェーン攻撃の標的となるポイントを削減します。
  • ジャストインタイム発行: 発行されるトークンは publish 処理中のみ有効なため、トークンのライフサイクル管理が最適化されます。
  • アイデンティティベースの認可: リポジトリのメタデータに基づいた認証により、公開権限を特定の実行環境へ厳密に限定できます。

移行手順

1. npm 側の設定

まず、npm パッケージ側で「この GitHub リポジトリからの publish を許可する」設定します。

  1. npmの設定画面を開く

    • npmjs.com にログインし、対象パッケージの Settings タブを開きます。
  2. Trusted Publisher を設定する
    npm Settings画面

    1. Trusted Publisher > Select your publisher セクションへ移動します。
    2. 該当する CI/CD provider をクリックします(今回は GitHub Actions を使用)。
    3. 表示されたフォームに、GitHub リポジトリの情報を入力して保存します。
      • Repository owner: GitHub のユーザー名または組織名
      • Repository name: リポジトリ名
      • Workflow filename: publish を実行する yaml ファイル名(例: deploy.yml
  3. Publishing access を変更する
    Trusted Publisher 設定画面

    • Publishing access セクションへ移動し、以下の設定を選択して保存します。
      • Require two-factor authentication and disallow tokens (recommended)
      • 理由: セキュリティを強化し、従来のトークンではなく Trusted Publisher 経由の認証のみを許可するため。

2. GitHub Actions の修正

.github/workflows/deploy.yml
  jobs:
    publish:
      runs-on: ubuntu-latest
      permissions:
        contents: write
+       id-token: write  # OIDCトークン発行に必須
      steps:
        - uses: actions/checkout@v4

        - uses: actions/setup-node@v4
          with:
-           node-version: "20"
+           node-version: "24" # 重要: npm v11.5.1以上が必要
            registry-url: "https://registry.npmjs.org/"

        - name: Publish
-         env:
-           NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
          run: npm publish

3. ハマりポイント:npm のバージョン

執筆時点の GitHub Actions ランナーに含まれる Node.js 20 や 22 では、同梱されている npm のバージョンが古く、OIDC に対応していない場合があります。
そのため、setup-node で明示的に Node.js 24(または npm のバージョンアップ)を指定する必要があります。

4. 仕上げ:Secrets の削除

移行後、不要になった npm トークンを削除します。
GitHub リポジトリの Settings > Secrets and variables > Actions から削除してください。

まとめ

OIDC 認証(Trusted Publishers)へ移行したことで、以下のメリットが得られました。

  • 「トークン期限切れ」による CI 失敗がゼロに
  • Secrets の管理・ローテーション作業からの解放
  • OIDC 利用によるセキュリティレベルの向上
  • provenance バッジの自動付与 - ビルド元が検証可能に(公開リポジトリ + 公開パッケージのみ)

参考資料

Discussion