Package Source Mapping
Safeguarding your software supply chain is crucial if you use a mix of public and private package sources. Use Package Source Mapping along side other best practices to help you fortify your supply chain against attacks.
Starting with NuGet 6.0, you can centrally declare which source each package in your solution should restore from in your nuget.config file.
The feature is available across all NuGet integrated tooling.
Older tooling will ignore the Package Source Mapping configuration. To use this feature, ensure all your build environments use compatible tooling versions.
Package Source Mappings will apply to all project types – including .NET Framework – as long as compatible tooling is used.
For a video-based overview of the Package Source Mapping feature, consider watching the Secure your NuGet packages with Package Source Mapping video on YouTube.
Enabling Package Source Mapping
To opt into this feature, you must have a
nuget.config file. Having a single
nuget.config at the root of your repository is considered a best practice. See nuget.config documentation to learn more.
- Declare your desired package sources in your
- Following your source declarations, add a
<packageSourceMapping>element that specifies the desired mappings for each source.
- Declare exactly one
packageSourceelement for each source in use.
- Add as many patterns as you find necessary.
<!-- Define the package sources, nuget.org and contoso.com. --> <!-- `clear` ensures no additional sources are inherited from another config file. --> <packageSources> <clear /> <!-- `key` can be any identifier for your source. --> <add key="nuget.org" value="https://api.nuget.org/v3/index.json" /> <add key="contoso.com" value="https://contoso.com/packages/" /> </packageSources> <!-- Define mappings by adding package patterns beneath the target source. --> <!-- Contoso.* packages and NuGet.Common will be restored from contoso.com, everything else from nuget.org. --> <packageSourceMapping> <!-- key value for <packageSource> should match key values from <packageSources> element --> <packageSource key="nuget.org"> <package pattern="*" /> </packageSource> <packageSource key="contoso.com"> <package pattern="Contoso.*" /> <package pattern="NuGet.Common" /> </packageSource> </packageSourceMapping>
Package Source Mapping settings are applied following nuget.config precedence rules when multiple
nuget.config files at various levels (machine-level, user-level, repo-level) are present.
Package Source Mapping rules
For maximum flexibility and control, NuGet requires that all packages match a package pattern through a well defined precedence.
Package Pattern requirements
All requested packages must map to one or more sources by matching a defined package pattern. In other words, once you have defined a
packageSourceMapping element you must explicitly define which sources every package - including transitive packages - will be restored from.
- Both top-level and transitive packages must match defined patterns. There is no requirement that a top level package and its dependencies come from the same source.
- The same ID pattern can be defined on multiple sources, allowing matching package IDs to be restored from any of the feeds that define the pattern. However, this isn't recommended due to the impact on restore predictability (a given package could come from multiple sources). This may be a valid configuration if you trust all respective sources.
Package Pattern Syntax
|Package prefix pattern||
||Must end with a
|Package ID pattern||
||Exact package ID.|
Package Pattern precedence
When multiple unique patterns match a package ID, the most specific one will be preferred. Package ID patterns always have the highest precedence while the generic
* always has the lowest precedence. For package prefix patterns, the longest has precedence.
Setting default sources
* pattern can be used to make a declare a de-facto default source - meaning any package that doesn't match other specified patterns will be restored from that source without throwing an error.
This configuration is advantageous if you primarily use packages from say,
nuget.org, and only have a few internal packages, or use standard prefixes for all internal packages like
If your team doesn't use standard prefixes for internal package IDs or vets
nuget.org packages prior to installation, then making a private source the default will suit your needs better.
When the requested package already exists in the global packages folder, no source look-up will happen and the mappings will be ignored. Consider declaring a global packages folder for your repo to gain the full security benefits of this feature. Work to improve the experience with the default global packages folder in planned for a next iteration. To learn more about how package installation works, see the conceptual document.
There are 2 ways you can fully onboard your repository, manually or using the NuGet.PackageSourceMapper tool.
For manual onboarding you may take the following steps:
- Declare a new global packages folder for your repo.
- Run dotnet restore to restore dependencies.
dotnet list package --include-transitiveto view all top-level and transitive packages in your solution.
- For .NET framework projects using
packages.configfile will have a flat list of all direct and transitive packages.
- For .NET framework projects using
- Define mappings such that every package ID in your solution - including transitive packages - matches a pattern for the target source.
- Run dotnet nuget locals global-packages -c to clear global-packages directory.
- Run restore to validate that you have configured your mappings correctly. If your mappings don't fully cover every package ID in your solution, the error messages will help you identify the issue.
- When restore succeeds, you are done! Optionally consider:
- Simplifying the configuration to fewer declarations by using broader package ID prefixes or setting a default source where possible.
- Verifying the source each package was restored from by checking the metadata files in the global packages folder or reviewing the restore logs.
Automated onboarding using tool
Many repositories have a large number of packages and doing the work manually can be time consuming. The NuGet.PackageSourceMapper tool can automatically generate a NuGet.config for you, based on your project's known packages and sources.
The package source mapper tool requires you to have completed a successful package restore in which it will read each respective
.nupkg.metadata file generated as part of your build to best understand how you map your respective packages and sources. Tool not only covers top dependencies it also considers all the transitive dependencies when generating mapping.
Tool has several option how to generate mapping pattern depending on your need, please check blog post and tool's readme instruction for more details.
For an idea of how your source mappings may look like, refer to our samples repo.
- There are no nuget.exe or dotnet.exe commands for managing the package source mapping configuration, see NuGet/Home#10735.
- There are no means of mapping packages at package installation time, see NuGet/Home#10730.
- There is a limitation when using the
DotNetCoreCLI@2Azure Pipelines task which can be worked around by using
feed-prefixes in your source mapping configuration. It is recommended however to use
NuGetAuthenticatefor your authentication needs and call the dotnet cli directly from a script task. See microsoft/azure-pipelines-tasks#15542.
Submit and view feedback for