Lock down your dependencies using configurable trust policies

December 05, 2018 by Ricardo Minguez (Rido)

For the past several months we have focused on various features to improve package security and trust. Around a year back, we had announced our plans on various signing functionalities that we have been implementing at a steady pace. We enabled package author signing and NuGet.org repository signing earlier this year. Continuing on the signing journey, we are happy to announce configurable client policies to secure developer environments for packages. With this feature, developers can now customize their environment to define package authors and/or package repositories they trust thereby allowing only trusted packages to be installed. This information is stored in the nuget.config file and can be configured to match your needs.

How to lock down your environment

Turn on require mode

You can enforce all your package dependencies to be signed just by enabling the require mode.

nuget.exe config -set signatureValidationMode=require

Configure trusted package repositories

You can then define your trust boundaries by specifying trustedSigners. For example,

  • You may just want to trust all packages available in NuGet.org:

     nuget.exe trusted-signers add -name NuGet.org -serviceindex https://api.nuget.org/v3/index.json
    
  • If you want to trust packages from specific NuGet authors/accounts, you can specify the collection of owners:

     nuget.exe trusted-signers add -name NuGet.org -serviceindex https://api.nuget.org/v3/index.json -owners microsoft;nuget
    

    NuGet.org adds repository signature to all new packages. We have started signing existing packages and we will announce when we are done. Subscribe to NuGet/Announcements repo for latest NuGet updates.

Configure trusted package authors

You can configure trust based on the author signature by specifying the certificate fingerprint in SHA256. You can get the SHA256 fingerprint from any signed package using the verify command. This enables you to consume packages from this trusted author irrespective of the package repository/source.

nuget.exe trusted-signers add -name Microsoft -certificateFingerprint 3F9001EA83C560D712C24CF213C3D312CB3BFF51EE89435D3430BD06B5D0EECE

You can also add trusted signers, author or repository, by using an existing signed package. For more information see the trusted-signers command reference.

Best practices

Share your nuget.config

nuget.config is a great option to share your settings across all your team members and even CI machines. If you keep your nuget.config file with the solution folder, install and restore operations will always use these settings. And this file can be easily shared along with your source code.

To create a nuget.config file you can use the dotnet new nugetconfig from your solution root folder.

Use a different global-packages folder

If you have different repos/solutions on your machine with different trust configurations, you must isolate the global-packages folder for each solution. This is because NuGet does trust validation only on package extraction to the globalPackagesFolder i.e. if a package is already present in the globalPackagesFolder, there is no check performed.

Example Config File

The following nuget.config file uses require mode and trusts packages in NuGet.org from the Microsoft account. Additionally, it also trusts packages signed with a private certificate.

Note that the global package folder has also been customized.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  
  <config>
    <add key="signatureValidationMode" value="require" />    
    <add key="globalPackagesFolder" value="%USERPROFILE%\.nuget\TrustedPackages" />
  </config>

 <packageSources>
    <clear />
    <add key="local" value="\\myserver\packages\" />
    <add key="nuget" value="https://api.nuget.org/v3/index.json" />
 </packageSources>
  
 <trustedSigners> 
  <author name="MyCompanyCert">
    <certificate fingerprint="F23175B9B052CE9C9D7E1546316F48A422DA3051FC79F4DB58ED5D78E372CEEC" 
                 hashAlgorithm="SHA256" 
                 allowUntrustedRoot="true" /> <!-- Enable private certificates-->
  </author>
   
  <repository name="nuget.org" serviceIndex="https://api.nuget.org/v3/index.json">
    <certificate fingerprint="0E5F38F57DC1BCC806D8494F4F90FBCEDD988B46760709CBEEC6F4219AA6157D" 
                 hashAlgorithm="SHA256" 
                 allowUntrustedRoot="false" />
    <owners>Microsoft</owners>
  </repository>
 </trustedSigners>
</configuration>

Reference documentation

Here are the docs for configuring package signature requirements, the nuget.config trustedSigners section, and the trusted-signers command.

Conclusion

Defining trust policies enable additional security checks to protect your entire dependency graph, not only for packages obtained from NuGet.org but also from any other package repository. As long as all the packages you consume are signed you can enable the require mode to detect any tampered, or unsigned package. It lets you control the authors and repositories that you trust.

For more information on how to protect your dependencies with signed packages, look at our documentation. If you have any feedback or encounter any issues while using this feature, do reach out to us by creating a GitHub issue or by tagging @nuget in your tweets.