Package source mapping tells NuGet which source each package ID may come from. Add a packageSourceMapping section to nuget.config, map every package ID, including transitive ones, to a source, then restore from a clean global packages folder. It needs NuGet 6.0 or later.
Why it exists
Microsoft's documentation says that by default NuGet searches all configured sources, and when a package exists on several, it may not be deterministic which one is used. Source mapping filters, per package, which sources NuGet searches. That removes the room dependency confusion needs.
Steps
- Check your tooling. The feature was added in NuGet 6.0 and works with .NET SDK 6.0.100 and later. Older tooling ignores the configuration, so make sure every build environment is current.
- Use one nuget.config at the repository root. The documentation calls that a best practice.
- Declare a repository-local global packages folder. If a package is already in the global packages folder, no source lookup happens and the mappings are ignored.
- Restore and list packages. Run a restore, then list all top-level and transitive packages.
- Write the mappings. Every package must match a pattern.
- Clear the global packages cache and restore again to prove the mapping works.
An example mapping
<configuration>
<packageSources>
<clear />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
<add key="contoso.com" value="https://contoso.com/packages/" />
</packageSources>
<packageSourceMapping>
<packageSource key="nuget.org">
<package pattern="*" />
</packageSource>
<packageSource key="contoso.com">
<package pattern="Contoso.*" />
</packageSource>
</packageSourceMapping>
</configuration>
Here Contoso.* IDs come from the internal feed and everything else from nuget.org.
Precedence rules
| Pattern | Meaning |
|---|---|
| Exact ID | Highest precedence |
| Prefix ending in a star | The longest matching prefix wins |
| A lone star | Lowest precedence, a default source |
If your team has no standard internal prefix, or vets public packages before use, the documentation suggests making the private source the default instead.
Gaps to know about
The documentation says mapping applies when NuGet downloads packages during restore, install and update. Commands such as dotnet list package and dotnet package add still send package IDs to all configured sources. Plan for that in your threat model.
An automated helper tool, NuGet.PackageSourceMapper, can generate a starting configuration from a restored project.
Click through it at your own pace, or open it full screen. Notice how transitive packages appear alongside direct ones, because you must map those too.
Quick check
Do I have to map transitive packages?
Yes. Once a mapping section exists, every package, including transitive ones, must match a pattern.
Why did my mapping seem to have no effect?
The package may already have been in the global packages folder, where the lookup is skipped. Clear it, or use a repository-specific folder.
Safeguard does SBOM and dependency scanning for .NET projects, and a free scan lists the transitive packages you need to map.
Sources
Last reviewed: 19 October 2026.