NuGet Trusted Publishingが2025年9月22日にアナウンスされ、OpenID Connect (OIDC)を使ってトークンレスでCIからNuGetパッケージを公開できるようになりました。
今回は、NuGet Trusted Publishingを使ってGitHub ActionsからトークンレスでNuGetパッケージを公開するメリットと手順を解説します。NuGet Trusted Publishingは積極的に使っていきましょう。
はじめに
NuGetに限らず、多くのパッケージシステムはPersonal Acces Token(PAT)を用いています。PATはシンプルで使いやすい反面、長期間有効であることや手動ローテーションが必要なことから、セキュリティ上の課題が指摘されています。
例えば利用者が特に多いnpmは、パッケージ作者から詐取したPATを使ってマルウェア入りパッケージを公開する事件が何度も発生しています。npmにおけるパッケージPAT認証の課題に対するGitHubの対策は「TOTPからPasskeyベースへの移行 (認証のフィッシング対策強化)」と「OIDCを使ったトークンレスパッケージ公開(Trusted Publishing)」です。npmにおいてTrusted Publishingが先行していているので、本記事と合わせて読むと参考になる記事を紹介します
本記事で紹介するNuGetのTrusted Publishingは、細かい違いはありつつもnpm Trusted Publishingと同様の仕組みを導入した考えて差し支えありません。
NuGetパッケージ公開の課題
C#や.NETでライブラリを配布する場合、.nupkgにパックしてnuget.orgへ公開します。従来、NuGetへパッケージ公開するには、PAT1を発行してdotnet nuget pushコマンドに渡す必要がありました。npm同様に、ここ数年はPATの課題が指摘されています。
- PATは長期間有効なので漏洩リスクが高い (最短1週間)
- PATは手動ローテーションなので運用コストが高い (最長1年)
- PATをCI/CD環境へ安全に渡す必要がある
- PATが漏れたらだれでもどこからでもパッケージを公開できてしまう
Trusted Publishingのメリットとリスク
トークンレスパッケージ公開は、「手元からパッケージ公開せずパッケージ公開はCI/CDからのみ行う」、という前提を置くことでPAT管理の煩雑さを解消します。
- 自動発行されたPATは短命
- ユーザーによるPATローテーションが不要になる
- CI/CD環境にPATを保存する必要がなくなる
- 登録したCI/CD環境(リポジトリ、ワークフローファイル名)だけパッケージを公開できる
トークンレスパッケージ公開を導入しても、以下のようなリスクは残ります。
- CI/CD環境へ不正アクセスされた場合、パッケージを公開されるリスクがある
- あくまでもパッケージ公開の認証を強化するものであり、パッケージ内容の改ざんやマルウェア混入を防止するものではない
NuGet Trusted Publishingの概要
Trusted PublishingはOIDCを使ってパッケージ公開時のサービス認証を行う仕組みです。OIDCの基本的な仕組みについては、業界で取り組んでいるOpenSSFイニシアチブ)を参照するとフローや概念がよくわかります。

NuGet Trusted Publishingを用いると、事前登録したCI/CD環境からのリクエストに対して短時間のみ有効なトークンを返し、これを使ってパッケージ公開できます。NuGet Trusted PublishingのOIDC認証フローは次の通りです。
- CI/CD環境(GitHub Actions)がOIDCトークンを発行
- NuGetにOIDCトークンを送りパッケージ公開用PATを取得(短命)
- PATを使ってNuGetパッケージを公開
Trusted Publishingを利用するには、GitHubからの公開設定を登録する必要があります。設定の流れは次の通りです。
- nuget.orgでTrusted Publishingのポリシーを設定
- CI/CDはポリシーに沿った設定でNuGetパッケージ公開
なお、NuGet Trusted PublishingはCI/CD環境としてGitHubに対応している一方、他のCI/CD環境は対応していません。2
設定方法
NuGet Trusted Publishingの設定手順を見ていきましょう。
nuget.orgでTrusted Publishingのポリシーを設定
Nugetにログインして、アカウントメニュー -> Trusted Publishingを開きます。

Createをクリックして、Trusted Publishingポリシーを作成します。下は私の管理しているSkiaSharp.QrCodeリポジトリの設定例です。
- ポリシー名は任意の名前でOK。識別しやすいようにリポジトリ名などを入れておくとよさそう
- Package OwnerはNuGetのアカウントを指定。ここでOrgアカウントを選択すれば、NuGet Orgアカウントのパッケージが対象となる
- Repository OwnerはGitHubのリポジトリ所有者名を指定。GitHub Orgのパッケージなら、GitHub Organization名を指定
- Repository Nameはリポジトリ名を指定
- Workflow Fileは、GitHub Actionsワークフローのファイル名を指定。注意書きにあるように、.github/workflows/以下の「ファイル名」のみを指定

GitHub Actionsワークフローの設定
GitHub Actionsのワークフローを設定します。ポイントは次の通りです。
- ワークフローファイル名はNuGet Trusted Publishingポリシーで指定したWorkflow Fileと一致させる
- Nuget/loginアクションを実行するジョブに
id-token: writeの権限を付与する3 - NuGet/loginアクションを使ってNuGetの短命トークン取得する4
サンプルのワークフローrelease.yamlは次の通りです。git tagでバージョンタグをプッシュしたときにパッケージを公開します。
name: Publish NuGet package on: push: tags: - 'v*.*.*' # バージョンタグをプッシュしたときに実行 jobs: publish: permissions: contents: read id-token: write # OIDCトークン発行のために必要 runs-on: ubuntu-24.04 steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 # ビルド & パック - name: dotnet pack run: dotnet pack -c Release -o ./bin # NuGet/loginアクションでOIDCトークンを使って短命トークンを取得 - name: NuGet Login uses: NuGet/login@d22cc5f58ff5b88bf9bd452535b4335137e24544 # v1.0.0 id: login with: user: my-nuget-username # NuGetのユーザー名を指定、Orgアカウントでもユーザー名となる # 取得した短命トークンを使ってパッケージを公開 - name: Push package run: dotnet nuget push ./bin/*.nupkg --api-key "${{ steps.login.outputs.NUGET_API_KEY }}" --source https://api.nuget.org/v3/index.json
ワークフローを実行
タグをプッシュすれば、GitHub ActionsがトリガーされてOIDCを使ってNuGetパッケージが公開されます。
制約
2025年10月1日時点で、Reusable WorkflowでNuGet/Loginを使った場合に、NuGetで登録したポリシーを見つけられないことを確認しています。Reusable Workflowを使わずに、直接ワークフローに記述する場合は問題ないので、こちらを利用することをお勧めします。
Error: Token exchange failed (401): No matching trust policy owned by user '***' was found.
これはNuGet側で対応しないといけなさそうな気配があるのでNuGet/loginのIssueで報告しました。今後の対応を待ちましょう。
- Organization Packages Policy couldn't found when using Reusable Workflow · Issue #6 · NuGet/login
- Workflow file name matching inconsistent · Issue #9 · NuGet/login
再現ワークフローです。
# `.github/workflows/nuget-push.yaml@main` name: Push NuGet on: workflow_call: jobs: create-release: permissions: contents: write id-token: write # required for NuGet Trusted Publish runs-on: ubuntu-24.04 timeout-minutes: 10 steps: - name: NuGet login (OIDC → temp API key) uses: NuGet/login@d22cc5f58ff5b88bf9bd452535b4335137e24544 # v1.1.0 id: login with: user: my-nuget-user
# 呼び出し元ワークフロー name: Build-Release on: workflow_dispatch: jobs: dummy: permissions: contents: write id-token: write # required for NuGet Trusted Publish uses: .github/workflows/nuget-push.yaml@main
まとめ
NuGetのPAT認証の課題を解決するTrusted Publishingが公開されました。これまではPATローテーション/対応パッケージの指定でわずらわしかったのですが、Trusted Publishingを使って認証管理をシンプルにできます。
とはいえ、認証の境界ラインがGitHub Actionsに移動するためセキュリティがザルだと意味がありません。GitHub Actionsのセキュリティ対策をしっかり行った上で、Trusted Publishingを導入することをお勧めします。2025年現在ならGitHub 2FAからSMSは削除し、Passkeyベースの認証に移行するのがよいでしょう。