手動でトークンを更新するのがめんどいので npm の Trusted Publisher の設定をする
- 投稿した日
- 更新した日
- 書いたひと
- ひらたけ

npm パッケージのサプライチェーン攻撃のニュースを頻繁に目にするようになった昨今。そんな中、先日 npm からトークンに関する変更の通知がメールで送られてきました。有効期限の長いトークンは良くないので 有効期限が無期限な Classic Token を 11 月上旬に廃止する とのこと。
Classic Token の他には Granular Access Token というトークンも発行できますが、こちらも有効期限に任意の日付を指定できたものが 最長 90 日に制限される ことに。
私はいくつかの npm パッケージを自作して公開しているのですが、セキュリティ的に大事なこととはいえ、頻繁にトークンを変更するのは大変。最長 90 日という有効期限も、今後はさらに短くなることがあるかもしれません。というわけで、そんなトークンの更新をしなくてもパッケージの公開ができる Trusted Publisher の設定をしてみることに。とりあえずパッケージを公開することができたので、備忘録的な感じで手順を書いておこうと思います。
Trusted Publisher は、OpenID Connect(OIDC) という仕組みを使って、GitHub Actions や GitLab CI/CD パイプラインから直接 npm パッケージを公開する仕組みとのこと。
あらかじめ設定さえしておけば、GitHub Actions や GitLab CI/CD パイプラインからであれば、こちらからトークンを発行して設定して…と管理をしなくても、ワークフロー実行時に専用トークンが発行されて良い感じに処理してくれる…らしい。設定できる Granular Access Token の最大有効期限がどれだけ短くなろうとも、そもそもトークンを発行しなくても良くなるので、期限が切れるたびにトークンを更新する作業が不要になります。
Trusted Publisher を設定してみる
npm で設定を行うパッケージの設定画面を開き、「Trusted Publisher」という見出しの部分から設定を進めます。現時点では「GitHub Actions」と「GitLab CI/CD」が設定可能となっていて、この投稿では GitHub Actions で設定を行います。
アスタリスクが付いている必須項目に、それぞれ情報を入力します。ユーザ名に大文字が含まれている場合、その部分はちゃんと大文字で入力する必要があります。私は小文字で入力してしまったせいで、エラーになる原因が分からず時間を溶かしました。
- Organization or user - 公開するパッケージのリポジトリが含まれる組織もしくはユーザのユーザ名
- Repository - 公開するパッケージのリポジトリ
- Workflow filename - リリース時に実行するワークフローのファイル名
また、Trusted Publisher の設定の下にある「Publishing access」で、recommended が付いている二要素認証必須かつトークンの禁止を選択してセキュリティレベルを向上させます。項目名に disallow tokens とありますが、Trusted Publisher でのパッケージ公開は行うことが可能です。
パッケージの設定を保存後、GitHub のリポジトリを開いて GitHub Actions のリリース用ワークフローを変更します。npm のドキュメント にある通り、permissions に id-token: write が必要なのと、npm のバージョンが 11.5.1 以上でないと動作しないため npm install -g npm@latest などを実行して npm の更新を行う必要があります。
以下は、パッケージマネージャーに pnpm を使用かつ semantic-release でバージョン番号を決めたりリリースノートを生成したりしているパッケージでのリリースワークフローです。
name: Release
on:
workflow_dispatch:
permissions:
contents: read
jobs:
release:
name: Release
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest]
node: [22]
timeout-minutes: 10
permissions:
contents: write
issues: write
pull-requests: write
id-token: write # Required for OIDC
steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
- name: Setup pnpm
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061
with:
run_install: false
- name: Setup Node.js
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903
with:
node-version: ${{ matrix.node }}
registry-url: 'https://registry.npmjs.org'
cache: 'pnpm'
# Ensure npm 11.5.1 or later is installed
- name: Update npm
run: npm install -g npm@latest
- name: Install dependencies
run: pnpm install
- name: Check dependencies
run: npm audit signatures
- name: Release package
run: pnpm semantic-release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
もともと設定していたワークフローから変更した点は、上記の permissions に id-token: write の追加と、npm を最新バージョン(11.5.1 以上)へ更新するため npm install -g npm@latest コマンドの実行の追加に加えて、actions/setup-node に registry-url: 'https://registry.npmjs.org' を設定した点と、これまで必要だった npm のトークンを環境変数に設定していたものを削除した点の 4 つです。
ワークフローを更新後、GitHub のリポジトリに設定している npm のトークンを削除します。これで準備は完了です。試しにワークフローを実行してみると、無事パッケージの新しいバージョンをリリースすることができました🎉
まとめ
GitHub Actions を利用する場合は、以下の方法で対応できました。
npmjs.comのパッケージの設定で「Trusted Publisher」を画面の指示に従って設定する- リリース用のワークフローのファイルを変更する
permissionsにid-token: writeを追加するactions/setup-node実行時にregistry-url: 'https://registry.npmjs.org'を指定する- パッケージ公開の処理を実行する前に npm を 11.5.1 以上に更新する(
npm install -g npm@latestを実行するなど) - Trusted Publisher の設定によって不要になる npm のトークンを削除する
メールで通知が届いたときは「なんか色々変わるっぽいけど…何したらいいんだ?」と困惑していましたが、定期的にトークンを更新する手間が増えるわけでもなくひと安心。手動でトークンを発行しなくても良い仕組みが広がることで、サプライチェーン攻撃が少しでも減ることに期待ですね。