Safeguard
Security Guides•

How do I store private NuGet feed credentials safely in CI?

Prefer a credential provider, then environment variables, and avoid clear text in nuget.config. Here is the order NuGet checks and the order to choose.

Safeguard Security Team
4 min read

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:

  1. An environment variable named NuGetPackageSourceCredentials followed by an underscore and the source name.
  2. Credentials in nuget.config files.
  3. A NuGet credential provider, if your feed offers one.

The order to prefer

Microsoft's guidance ranks the options differently from the lookup order.

RankOptionNotes
1Credential providerAvoids secrets in plain text and files in source control
2Encrypted credentials in nuget.configWindows only, decryptable only by the same user on the same machine
3Environment variable macros in nuget.configThe file shows where the secret comes from
4Environment variables directlyLess visible, but fine in pipelines
5Clear text in nuget.configLast 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

  1. Commit a nuget.config with the source list and a clear element, but no secrets.
  2. Store the token in your CI secret store, not in the repository.
  3. Expose it to the job as an environment variable, scoped to the restore step.
  4. Use a token with the narrowest scope your feed allows, and a short life.
  5. Rotate the token on a schedule and after any suspected leak.
  6. 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

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.