Use a credential provider first. If none exists for your feed, use environment variable macros or the NuGetPackageSourceCredentials variable, and keep clear text passwords out of any nuget.config in source control. NuGet looks for credentials in a fixed order, but Microsoft recommends a different order for safety.
How NuGet finds credentials
For an HTTP feed, NuGet first makes an unauthenticated request. If the server answers with a 401, it searches in this order:
- An environment variable named NuGetPackageSourceCredentials followed by an underscore and the source name.
- Credentials in nuget.config files.
- A NuGet credential provider, if your feed offers one.
The order to prefer
Microsoft's guidance ranks the options differently from the lookup order.
| Rank | Option | Notes |
|---|---|---|
| 1 | Credential provider | Avoids secrets in plain text and files in source control |
| 2 | Encrypted credentials in nuget.config | Windows only, decryptable only by the same user on the same machine |
| 3 | Environment variable macros in nuget.config | The file shows where the secret comes from |
| 4 | Environment variables directly | Less visible, but fine in pipelines |
| 5 | Clear text in nuget.config | Last resort, risky if committed |
The environment variable format
The variable name uses your exact source key, and the value follows a fixed pattern.
export NuGetPackageSourceCredentials_Contoso="Username=ci-user;Password=$TOKEN;ValidAuthenticationTypes=Basic"
Two traps from the docs. If the value does not match the expected pattern, NuGet silently ignores it. And because the variable outranks the config file, an expired secret in a variable can mask a fresh one in a file, with no log line to tell you.
Steps for a clean CI setup
- Commit a nuget.config with the source list and a clear element, but no secrets.
- Store the token in your CI secret store, not in the repository.
- Expose it to the job as an environment variable, scoped to the restore step.
- Use a token with the narrowest scope your feed allows, and a short life.
- Rotate the token on a schedule and after any suspected leak.
- Run restore non interactively so a credential provider never waits for a person.
Build agent hygiene
Microsoft also warns that agents which are not reset after each build carry risk. Packages from authenticated sources may remain in the build output, and NuGet's cache folders can be read by other users on shared machines. Point the global packages, cache and temp folders at directories that are cleaned after every build, and clean the repository even when the build fails.
On Linux, make sure no other account can read a nuget.config that contains credentials.
Try it yourself
Click through it at your own pace, or open it full screen. A pull request check is where an accidentally committed password should be caught before merge.
Safeguard's compliance and evidence automation and policy gates help you show that pipeline controls exist, and a free scan checks your dependencies.
Quick check
Is it safe to put a password in nuget.config if the repo is private?
It is still risky. Clear text secrets in a file tracked by source control are easy to leak. Prefer a provider or environment variables.
Why does NuGet ignore my credential variable?
The name must match the source key and the value must follow the expected pattern, or NuGet skips it without logging.
Sources
- Consuming packages from authenticated feeds, Microsoft Learn
- Best practices for a secure software supply chain, Microsoft Learn
Last reviewed: 19 October 2026.