-
Notifications
You must be signed in to change notification settings - Fork 496
Add Trusted Publishing doc #3442
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
etvorun
wants to merge
7
commits into
main
Choose a base branch
from
evgenyt-trusted-publishing
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
2d88d79
Add Trusted Publishing doc
etvorun 9aef78f
Add Temporarily Enabled Policies section
etvorun 4c44c87
Policy Ownership Warnings
etvorun 98587b5
Updated YAML sample
etvorun 5c85715
Tweaks
etvorun 94dc80e
UX review feedback
etvorun 4242d16
CR feedback
etvorun File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
--- | ||
title: Trusted Publishing | ||
description: Trusted Publishing on nuget.org | ||
author: etvorun | ||
ms.author: evgenyt | ||
ms.date: 07/01/2025 | ||
ms.topic: conceptual | ||
--- | ||
|
||
# Trusted Publishing on nuget.org | ||
|
||
Trusted Publishing is a better way to publish NuGet packages. You don’t need to manage long-lived API keys anymore. Instead, you use short-lived credentials issued by your CI/CD system, like GitHub Actions. | ||
|
||
This makes your publishing process safer by reducing the risk of leaked credentials. It also makes automation easier because you don’t need to rotate or store secrets. This approach is part of a broader industry shift toward secure, keyless publishing. If you're curious, check out the OpenSSF initiative: https://repos.openssf.org/trusted-publishers-for-all-package-repositories. | ||
|
||
> ⚠️ **Heads up:** If you don’t see the **Trusted Publishing** option in your nuget.org account, it might not be available to you yet. We’re rolling it out gradually. | ||
|
||
## How it works | ||
|
||
Here’s the basic flow: | ||
|
||
1. Your CI/CD system (like GitHub Actions) runs a workflow. | ||
2. It issues a short-lived token. | ||
3. That token is sent to nuget.org. | ||
4. NuGet verifies it and returns a temporary API key. | ||
5. Your workflow uses that key to push the package. | ||
|
||
 | ||
|
||
NuGet’s temporary API keys are valid for **15 minutes**, so your workflow should request the key shortly before publishing. | ||
If you request it too early, it might expire before the push happens. | ||
|
||
Each short-lived token can only be used once to obtain a single temporary API key—one token, one API key. | ||
|
||
This setup gives you a secure and automated way to publish packages, without the risks that come with long-lived secrets. | ||
|
||
|
||
## GitHub Actions Setup | ||
|
||
To get started: | ||
|
||
1. Log into nuget.org. | ||
2. Click your username and choose **Trusted Publishing**. | ||
3. Add a new trusted publishing policy. You’ll need to provide your GitHub org, repo, workflow file, and few other details. | ||
4. In your GitHub repo, update your workflow to request a short-lived API key and push your package. | ||
|
||
Here’s a basic example: | ||
|
||
```yaml | ||
jobs: | ||
build-and-publish: | ||
permissions: | ||
id-token: write # enable GitHub OIDC token issuance for this job | ||
|
||
steps: | ||
# Build your artifacts/my-sdk.nupkg package here | ||
|
||
# Get a short-lived NuGet API key | ||
- name: NuGet login | ||
id: nuget_login | ||
uses: nuget/login@v1 | ||
with: | ||
user: ${{secrets.NUGET_USER}} | ||
source: https://api.nuget.org/v3/index.json | ||
|
||
# Push the package | ||
- name: NuGet push | ||
run: dotnet nuget push artifacts/my-sdk.nupkg -k ${{steps.nuget_login.outputs.NUGET_API_KEY}} -s https://api.nuget.org/v3/index.json | ||
``` | ||
|
||
|
||
## Policy Ownership | ||
|
||
When you create a Trusted Publishing policy, you need to choose who owns it. The owner can be either: | ||
|
||
- **You (an individual user)** | ||
- **An organization you belong to** | ||
|
||
The policy will apply to all packages owned by the selected owner. That means it controls who can publish or modify those packages using Trusted Publishing. | ||
|
||
If you choose an organization, make sure you're an active member. If you leave the org later, the policy may become inactive until you're added back. | ||
|
||
Choosing the right owner helps ensure your publishing setup stays secure and aligned with your team’s structure. | ||
|
||
|
||
## Policies Pending Full Activation | ||
|
||
Sometimes when you create a Trusted Publishing policy, it starts out as temporarily active for 7 days. This usually happens with private GitHub repos. You’ll see this status in the UI. During that time, it behaves like a regular policy. But if no publish happens within those 7 days, the policy automatically becomes inactive. You can restart the 7-day window at any time—even after it expires. | ||
|
||
Why is this temporary period necessary? Because NuGet needs GitHub repository and owner IDs to lock the policy to the original repo and owner. That helps prevent resurrection attacks. Without those IDs, someone could delete a repo, recreate it with the same name, and try to publish as if nothing changed. | ||
|
||
Once a successful publish provides the IDs (as part of GitHub’s short-lived token), the policy becomes permanently active. | ||
|
||
|
||
## Policy Ownership Warnings | ||
|
||
Trusted Publishing policies are tied to a specific owner—either an individual user or an organization. | ||
If something changes with that ownership, the policy might become inactive. When that happens, you'll see a warning in the UI. | ||
|
||
### Common cases | ||
|
||
- **User removed from organization** | ||
If a policy is owned by an organization and the user who created it is later removed from that org, the policy becomes inactive. | ||
If the user is added back to the organization, the policy will be active again automatically. | ||
|
||
- **Organization is no longer active** | ||
If the organization that owns the policy is locked or deleted, the policy becomes inactive. | ||
|
||
These warnings help make sure that only active, secure policies are used when publishing packages. |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.