NuGet API Keyの30日制限とは?11月1日のCI停止を防ぐTrusted Publishing移行手順

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を放置した場合、パイプライン全体が最初から失敗するとは限りません。

一般的には、次の処理までは正常に完了します。

  1. ソースコードのチェックアウト
  2. パッケージの復元
  3. ビルド
  4. テスト
  5. dotnet pack
  6. 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へ切り替え、公開経路を確保してください。

公開ワークフローとキーの利用先を一覧化する

最低限、次の項目を表にまとめます。

確認項目記録する内容
リポジトリパッケージのソースコードがある場所
パッケージIDNuGet.orgへ公開するパッケージ名
CI/CDGitHub 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側の更新が完了していなければ、直後から公開が停止します。

より安全なのは、次の順序です。

  1. 別名で新しいAPI Keyを作る
  2. CI/CDに一時的な新シークレットとして登録する
  3. ワークフローを新シークレットへ切り替える
  4. 実際のパッケージ公開を1回成功させる
  5. 古い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を使ってワークフローの身元を確認する公開方式です。

処理の流れは次のようになります。

  1. GitHub ActionsやGitLabのジョブがOIDCトークンを発行する
  2. ワークフローがOIDCトークンをNuGet.orgへ送る
  3. NuGet.orgが登録済みのTrusted Publishingポリシーと照合する
  4. 条件が一致すれば、一時的なNuGet API Keyが発行される
  5. 一時キーを使ってパッケージを公開する

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 Ownercontoso
Repositorycontoso-sdk
Workflow Filepublish.yml
Environmentrelease
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”

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次