NuGet.orgへパッケージを公開している開発者は、2026年11月1日までにCI/CDの認証設定を見直す必要があります。2026年8月17日以降に新規作成するNuGet API Keyは最長30日間に制限され、同日より前に作成された既存キーも2026年11月1日に失効します。対策しなければ、ビルドやテストは成功しても、最後のパッケージ公開処理だけが認証エラーで停止する可能性があります。([Microsoft for Developers][1])
当面の停止回避策は、新しいAPI Keyを作成してCIのシークレットを更新することです。ただし、30日ごとのローテーションを恒常的に続けるより、GitHub ActionsまたはGitLabを利用している環境では、長期シークレットを保存しないNuGet Trusted Publishingへ移行する方が安全で運用負担も小さくなります。
NuGet API Keyの30日制限で何が変わったのか
Microsoftが発表したNuGet API Keyの変更内容は、次のとおりです。
| 日付 | 変更内容 | 実務への影響 |
|---|---|---|
| 2026年8月17日 | 新規API Keyの有効期間が最長30日になる | 従来のような長期間のキーを新規発行できない |
| 2026年8月17日 | 新規キーで365日の有効期間を選べなくなる | API Keyを使い続ける場合は定期更新が必須になる |
| 2026年11月1日 | 8月17日より前に作成された既存API Keyが失効する | 古いキーを保存したCI/CDが一斉に公開失敗する可能性がある |
今回の変更は、API Keyを廃止するものではありません。しかし、NuGet.orgは今後、API Keyの有効期間をさらに短縮する可能性にも言及しています。したがって、30日ごとの更新作業を作り込むだけでは、長期的な解決にならない可能性があります。([Microsoft for Developers][1])
影響を受ける処理と受けない処理
今回の対象は、NuGet.orgへパッケージを公開するためのAPI Keyです。
| 処理 | 影響 |
|---|---|
dotnet nuget pushによる公開 | 影響あり |
nuget pushによる公開 | 影響あり |
| GitHub ActionsからNuGet.orgへの公開 | API Key方式なら影響あり |
| GitLab CI/CDからNuGet.orgへの公開 | API Key方式なら影響あり |
| Azure Pipelines、Jenkinsなどからの公開 | NuGet.org API Keyを使っていれば影響あり |
dotnet restoreによるパッケージ取得 | 直接の影響なし |
| Visual Studioでのパッケージインストール | 直接の影響なし |
| Azure Artifactsなど別フィードへの認証 | NuGet.orgのAPI Key変更とは別 |
| NuGet.orgのWeb画面からの手動アップロード | 引き続き利用可能 |
NuGet.orgのAPI Keyは、プライベートフィードへログインするための認証情報とは別物です。今回の変更だけを理由に、すべてのNuGet設定やNuGet.Configを書き換える必要はありません。まずは、NuGet.orgへの公開処理に対象を絞って調査します。([Microsoft Learn][2])
リポジトリ内で最初に検索する文字列
CI/CDの設定ファイルやスクリプトから、次の文字列を検索してください。
NUGET_API_KEY
NUGET_TOKEN
NUGET_AUTH_TOKEN
NuGetApiKey
dotnet nuget push
nuget push
api.nuget.org
www.nuget.org/api/v2/package
GitHub ActionsではRepository SecretsやOrganization Secrets、GitLabではCI/CD Variables、Azure PipelinesではVariable GroupやService Connectionも確認します。
コード上にキーが直接書かれていなくても、独自のシェルスクリプトやPowerShellスクリプトが環境変数からAPI Keyを読み込んでいる場合があります。リポジトリ内の検索だけでなく、CI/CD側のシークレット管理画面まで調査することが重要です。
11月1日に発生しやすいCI障害
古いAPI Keyを放置した場合、パイプライン全体が最初から失敗するとは限りません。
一般的には、次の処理までは正常に完了します。
- ソースコードのチェックアウト
- パッケージの復元
- ビルド
- テスト
dotnet pack- NuGet.orgへの
pushで失敗
API Keyが必要になるのは主に公開処理です。そのため、通常のプルリクエストでは問題が見つからず、タグを付けた本番リリース時に初めて障害が判明することがあります。dotnet nuget pushではAPI Keyを指定してNuGet.orgへパッケージを送信するため、失効したキーでは認証または権限確認の段階で失敗します。([Microsoft Learn][2])
特に注意が必要なのは、次のような環境です。
- リリースが数か月に一度しか実行されない
- 複数のリポジトリで同じAPI Keyを共有している
- 退職者や異動者のNuGet.orgアカウントがキーの所有者になっている
- パッケージごとに別の公開パイプラインが存在する
- 通常リリースと緊急リリースで異なるワークフローを使っている
- Organization SecretsとRepository Secretsに同名のキーがある
- 古いリリースブランチに別の公開スクリプトが残っている
「普段使っているワークフローを1本直したから完了」と判断せず、NuGet.orgにパッケージを公開できる経路をすべて洗い出す必要があります。
RotateとTrusted Publishingのどちらを選ぶべきか
対応方法は、大きく3つあります。
| 方法 | 向いている環境 | メリット | デメリット |
|---|---|---|---|
| 30日API Keyへローテーション | Trusted Publishingへすぐ移行できないCI | 既存パイプラインをほぼ維持できる | 30日以内ごとの更新が必要 |
| Trusted Publishingへ移行 | GitHub Actions、GitLab | 長期API Keyの保存と定期更新が不要 | 初回のポリシー設定が必要 |
| Web画面から手動公開 | 緊急時や公開頻度が極端に低い場合 | CIの改修なしで公開できる | 自動化できず、作業ミスが起きやすい |
GitHub ActionsまたはGitLabで継続的にパッケージを公開する場合は、Trusted Publishingを第一候補にします。
それ以外のCI/CD環境では、まず新しい30日API Keyへ切り替えて停止を防ぎます。そのうえで、NuGet.org側の対応環境追加を確認しながら、長期シークレットを使わない方式へ移行します。Microsoftも、GitHub ActionsとGitLabの利用者にはTrusted Publishingへの移行を推奨し、その他の環境には30日キーを扱えるよう準備することを求めています。([Microsoft for Developers][1])
まずCI停止を防ぐAPI Keyローテーション手順
Trusted Publishingへの移行に時間がかかる場合でも、2026年11月1日まで何もしないのは危険です。先に新しいAPI Keyへ切り替え、公開経路を確保してください。
公開ワークフローとキーの利用先を一覧化する
最低限、次の項目を表にまとめます。
| 確認項目 | 記録する内容 |
|---|---|
| リポジトリ | パッケージのソースコードがある場所 |
| パッケージID | NuGet.orgへ公開するパッケージ名 |
| CI/CD | GitHub Actions、GitLab、Azure Pipelinesなど |
| ワークフロー | YAMLファイル名、ジョブ名 |
| シークレット名 | NUGET_API_KEYなど |
| キー所有者 | 個人または組織 |
| 最終公開日 | 最後に正常公開できた日 |
| 対応方法 | API Key更新またはTrusted Publishing |
複数のパッケージを管理している場合は、リポジトリ単位ではなく、公開されるパッケージID単位でも確認します。
新しいAPI Keyは必要最小限の権限で作る
NuGet.orgへサインインし、アカウントメニューからAPI Keysを開きます。新しいキーを作成するときは、すべてのパッケージを対象にした強いキーを安易に作らないようにします。
設定の目安は次のとおりです。
- 公開専用ならPush権限だけを付ける
- 対象パッケージをGlob Patternで限定する
- チームやパイプラインごとにキーを分ける
- 用途と更新時期が分かるキー名にする
- Unlist権限が不要なら付けない
例えば、Contoso.Logging系列だけを公開するなら、次のようなGlob Patternを検討します。
Contoso.Logging*
Scoped API Keyでは、操作権限と対象パッケージを限定できます。キーが漏えいした場合の影響範囲を小さくするため、実際に必要なパッケージだけを対象にしてください。([Microsoft Learn][3])
Refreshではなく新規キーを並行作成する
既存キーの「Refresh」をすぐに実行すると、古いキーはその時点で利用できなくなります。CI側の更新が完了していなければ、直後から公開が停止します。
より安全なのは、次の順序です。
- 別名で新しいAPI Keyを作る
- CI/CDに一時的な新シークレットとして登録する
- ワークフローを新シークレットへ切り替える
- 実際のパッケージ公開を1回成功させる
- 古いAPI Keyを削除する
NuGet.orgでは複数のScoped API Keyを作成できます。Refreshは同じ権限設定で新しい値を発行しますが、旧キーは即座に無効になります。そのため、無停止で切り替えるには新旧キーを一時的に並行させる方が安全です。([Microsoft Learn][3])
実際のpushまでテストする
シークレットを登録しただけでは、次の問題を検出できません。
- コピーしたキーが誤っている
- 対象パッケージがスコープに含まれていない
- CIが別のシークレットを参照している
- Organization Secretsの利用許可が不足している
- 公開ジョブだけ別のEnvironmentを使っている
通常のリリースを待たず、計画したプレリリース版や影響の小さい更新で、実際のpushまで確認してください。
dotnet nuget push "./artifacts/*.nupkg" \
--api-key "$NUGET_API_KEY" \
--source https://api.nuget.org/v3/index.json \
--skip-duplicate
--skip-duplicateは、既に同じバージョンが存在するときの409 Conflictを警告として扱うオプションです。認証エラーや権限不足を無視するものではありません。([Microsoft Learn][4])
30日キーを使い続ける場合は20~25日で更新する
有効期限当日に更新する運用は避けます。担当者の休暇、休日、CI障害などが重なると、更新できないまま失効する可能性があります。
社内ルールとしては、次のような設計が現実的です。
- 発行から20~25日で次のキーを作成する
- 新旧キーを一時的に並行運用する
- 公開成功後に旧キーを削除する
- 更新担当者を複数人にする
- 期限と利用先を台帳で管理する
- メール通知だけに依存しない
ただし、この作業を毎月続ける必要があるため、対応可能なCI/CDではTrusted Publishingへ移行した方が効率的です。
NuGet Trusted Publishingとは
NuGet Trusted Publishingは、固定されたAPI KeyをCI/CDへ保存せず、OIDCを使ってワークフローの身元を確認する公開方式です。
処理の流れは次のようになります。
- GitHub ActionsやGitLabのジョブがOIDCトークンを発行する
- ワークフローがOIDCトークンをNuGet.orgへ送る
- NuGet.orgが登録済みのTrusted Publishingポリシーと照合する
- 条件が一致すれば、一時的なNuGet API Keyが発行される
- 一時キーを使ってパッケージを公開する
NuGet.orgが発行する一時API Keyの有効期間は1時間です。また、1つのOIDCトークンから取得できる一時API Keyは1つです。ビルド開始時ではなく、dotnet nuget pushの直前にログイン処理を配置するのが重要です。([Microsoft Learn][5])
Trusted Publishingへ移行すると、次の管理が不要になります。
- 長期API KeyをGitHub Secretsなどへ保存する
- 30日ごとにキーを作り直す
- 複数リポジトリへ新しいキーを配布する
- 古いシークレットが残っていないか追跡する
さらに、リポジトリ、ワークフローファイル、Environmentなどの情報をポリシーとして照合できます。単に「正しい秘密文字列を持っているか」ではなく、「許可されたワークフローからの実行か」を確認できる点が大きな違いです。([Microsoft Learn][5])
GitHub ActionsをTrusted Publishingへ移行する手順
NuGet.org側でポリシーを作成する
NuGet.orgへサインインし、アカウントメニューからTrusted Publishingを開きます。
GitHub Actions用のポリシーには、主に次の情報を設定します。
| 項目 | 設定例 |
|---|---|
| Policy Owner | 個人アカウントまたは所属組織 |
| Repository Owner | contoso |
| Repository | contoso-sdk |
| Workflow File | publish.yml |
| Environment | release |
| Package Scope | 公開を許可するパッケージ |
Workflow Fileには、.github/workflows/publish.ymlではなく、ファイル名のpublish.ymlだけを入力します。
Environmentは任意ですが、本番公開にGitHub Environmentsを使っている場合は設定を推奨します。その場合、GitHub Actionsのジョブ側にも同じEnvironment名を指定してください。ポリシーでは公開操作と対象パッケージのスコープも制限できます。([Microsoft Learn][5])
GitHub ActionsのAPI Key参照を置き換える
次は、Trusted Publishingを利用する基本的なワークフロー例です。
name: Publish NuGet package
on:
workflow_dispatch:
push:
tags:
- "v*"
permissions:
contents: read
id-token: write
jobs:
publish:
runs-on: ubuntu-latest
environment: release
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Setup .NET
uses: actions/setup-dotnet@v6
with:
global-json-file: global.json
- name: Restore
run: dotnet restore
- name: Pack
run: dotnet pack --configuration Release --no-restore --output ./artifacts
# 一時キーの有効期間を無駄にしないよう、pack後に実行する
- name: NuGet login with OIDC
id: nuget-login
uses: NuGet/login@v1
with:
user: ${{ vars.NUGET_USER }}
- name: Push package
run: >
dotnet nuget push "./artifacts/*.nupkg"
--api-key "${{ steps.nuget-login.outputs.NUGET_API_KEY }}"
--source https://api.nuget.org/v3/index.json
--skip-duplicate
NUGET_USERにはメールアドレスではなく、NuGet.orgのプロフィール名を設定します。機密情報ではないためGitHub Repository Variableに保存できますが、組織の運用ルールに合わせて管理してください。
リポジトリにglobal.jsonがない場合は、global-json-fileを削除し、対象プロジェクトに合わせたSDKを指定します。
- name: Setup .NET
uses: actions/setup-dotnet@v6
with:
dotnet-version: "10.0.x"
NuGet/login@v1はGitHubのOIDCトークンをNuGet.org側のトークンサービスと交換し、NUGET_API_KEYという出力で一時キーを後続ステップへ渡します。OIDCトークンを取得するため、id-token: writeが必要です。contents: readはチェックアウトなどに使用します。([GitHub][6])
最初の公開は手動実行できるようにする
移行直後は、workflow_dispatchから手動実行できるようにしておくと確認しやすくなります。
確認するポイントは次のとおりです。
- OIDCログインステップが成功する
- 一時API Keyが出力として取得される
- 対象パッケージのpushが成功する
- NuGet.orgで新しいバージョンを確認できる
- API Keyを保存した旧シークレットを削除できる
- NuGet.orgの旧API Keyを削除できる
API Key方式を先に削除してしまうと、OIDC設定に問題があった場合に公開手段を失います。Trusted Publishingで1回以上正常に公開した後、旧シークレットと旧API Keyを削除してください。
プライベートリポジトリでは7日間の初回公開期限に注意する
プライベートGitHubリポジトリなどでは、作成したTrusted Publishingポリシーが最初の7日間だけ一時的に有効になる場合があります。
これは、最初の正常公開時にNuGet.orgがリポジトリIDや所有者IDを取得し、同名リポジトリの再作成を利用したなりすましを防ぐためです。7日以内に一度も公開しなかった場合、ポリシーが非アクティブになることがあります。その場合はNuGet.org側で有効化期間を再開してからテストしてください。([Microsoft Learn][5])
GitLab CI/CDをTrusted Publishingへ移行する手順
GitLabでは、ジョブにid_tokensを設定し、発行されたOIDCトークンをNuGet.orgのトークン交換エンドポイントへ送信します。
基本構成は次のとおりです。
stages:
- publish
publish_nuget:
stage: publish
image: mcr.microsoft.com/dotnet/sdk:10.0
id_tokens:
NUGET_ID_TOKEN:
aud: "https://www.nuget.org"
variables:
NUGET_USERNAME: "your-nuget-username"
NUGET_TOKEN_ENDPOINT: "https://www.nuget.org/api/v2/token"
NUGET_SOURCE: "https://www.nuget.org/api/v2/package"
script:
- dotnet restore
- dotnet pack --configuration Release --no-restore --output ./artifacts
- apt-get update
- apt-get install -y curl jq
- |
RESPONSE="$(curl --fail-with-body --silent --show-error \
-X POST "$NUGET_TOKEN_ENDPOINT" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $NUGET_ID_TOKEN" \
-d "{\"username\":\"$NUGET_USERNAME\",\"tokenType\":\"ApiKey\"}")"
NUGET_API_KEY="$(printf '%s' "$RESPONSE" | jq -r '.apiKey')"
if [ -z "$NUGET_API_KEY" ] || [ "$NUGET_API_KEY" = "null" ]; then
echo "NuGet temporary API key could not be obtained."
exit 1
fi
dotnet nuget push "./artifacts/*.nupkg" \
--source "$NUGET_SOURCE" \
--api-key "$NUGET_API_KEY" \
--skip-duplicate
NuGet.org側には、GitLabのnamespace、project、必要に応じてenvironmentやrefを登録します。ポリシーにrefを設定する場合、公式ドキュメントではブランチ名が対象とされ、タグは使用できないとされています。タグリリースを利用している場合は、ref条件を安易に追加しないようにしてください。([Microsoft Learn][5])
また、RESPONSEやNUGET_API_KEYをechoで出力しないでください。一時キーであっても、有効期間中は公開権限を持つ認証情報です。
Trusted Publishingで失敗しやすいポイント
| 症状 | 主な原因 | 確認箇所 |
|---|---|---|
| OIDCトークンを取得できない | id-token: writeがない | GitHub Actionsのpermissions |
| NuGetログインが失敗する | ポリシーとリポジトリ情報が一致しない | Owner、Repository、Workflow File |
| Environment指定時だけ失敗する | ポリシーとジョブのEnvironment名が違う | environment: releaseなど |
| ログイン成功後にpushが失敗する | パッケージスコープまたは公開権限が不足 | Trusted PublishingのPolicy Scopes |
| NuGetユーザーが見つからない | メールアドレスを指定している | userまたはNUGET_USERNAME |
| 長時間のビルド後にpushが失敗する | 一時キーの有効期限切れ | ログインステップの配置 |
| プライベートリポジトリで突然使えなくなった | 7日以内に初回公開しなかった | ポリシーのActivation Status |
| API Key更新直後に旧CIが停止した | Refreshで旧キーを即時無効化した | API Keys画面とシークレット更新状況 |
| 再実行時だけ重複エラーになる | 同じバージョンを既に公開済み | パッケージバージョン、--skip-duplicate |
特に多いのは、Workflow Fileへフルパスを入力するミスと、id-token: writeの指定漏れです。
また、一時API Keyは1時間で失効するため、テスト、コード署名、パッケージ生成などの時間がかかる処理をすべて終えた後に、NuGet/login@v1を実行してください。([Microsoft Learn][5])
2026年11月1日までの対応チェックリスト
すぐに実施すること
- NuGet.orgへ公開している全パッケージを一覧化する
dotnet nuget pushとnuget pushを全リポジトリから検索する- CI/CDのシークレット管理画面を確認する
- 8月17日より前に作成したキーの利用先を特定する
- キー所有者のアカウントが現在も管理可能か確認する
GitHub ActionsまたはGitLabを利用している場合
- NuGet.orgにTrusted Publishingポリシーを作成する
- パッケージスコープを必要最小限にする
- OIDCトークン発行権限を追加する
- 一時キー取得処理をpush直前に配置する
- 実際のパッケージを1回公開する
- 成功後に旧シークレットと旧API Keyを削除する
その他のCI/CDを利用している場合
- 新しい30日API Keyを作成する
- 旧キーを残したまま新キーへ切り替える
- 実際のpushを成功させる
- 旧キーを削除する
- 20~25日単位の更新スケジュールを設定する
- Trusted Publishingの対応状況を定期的に確認する
30日キーへの更新だけで終わらせない
今回の変更で最も避けるべきなのは、2026年11月1日の本番リリースで初めてAPI Keyの失効に気付くことです。
まず、NuGet.orgへ公開するすべてのパイプラインを洗い出してください。Trusted Publishingへすぐ移行できない環境では、新しいScoped API Keyを作り、実際のpushまで確認します。
GitHub ActionsまたはGitLabを利用している場合は、30日ごとのキー交換を恒久運用にするのではなく、Trusted Publishingへ移行するのが本命です。長期シークレットをCI/CDから取り除けば、キーの漏えいリスクだけでなく、更新忘れによるリリース停止も防ぎやすくなります。
対応順序は、利用先の調査、新しい認証方式の設定、実際の公開テスト、旧キーの削除です。設定画面を変更しただけで完了とせず、NuGet.orgへパッケージが正常に公開されるところまで確認してください。
[1]: https://devblogs.microsoft.com/dotnet/strengthening-nuget-supply-chain-security-reducing-api-key-lifetime/ “Strengthening NuGet Supply Chain Security: Reducing API Key Lifetime – .NET Blog”
[2]: https://learn.microsoft.com/en-us/nuget/nuget-org/publish-a-package “How to publish NuGet packages | Microsoft Learn”
[3]: https://learn.microsoft.com/en-us/nuget/nuget-org/scoped-api-keys “Scoped API keys | Microsoft Learn”
[4]: https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-nuget-push “dotnet nuget push command – .NET CLI | Microsoft Learn”
[5]: https://learn.microsoft.com/nuget/nuget-org/trusted-publishing “Trusted Publishing | Microsoft Learn”
[6]: https://github.com/NuGet/login “GitHub – NuGet/login: Connect to nuget.org · GitHub”

コメント