Search code examples
c#.netnuget

Nuget private source - possible to set condition in PackageReference?


I'm setting up a private nuget source via github. All is working well, using a nuget.config like this (credentials section redacted):

<configuration>
  <packageSources>
    <add key="github" value="https://nuget.pkg.github.com/<my-company>/index.json" />
  </packageSources>
  <packageSourceCredentials>...</packageSourceCredentials>
</configuration>

Note, I'm not clearing other packageSources: I still need to use the public nuget source. I'm just adding an additional private source in addition.

As I said, all is working, and I can add packages just fine from either source. But I got to worrying when I checked the PackageReference entries in the csproj. It doesn't indicate which source to use for the package.

For example, in this instance, MyCompany.Common is coming from my private source, and Newtonsoft.Json is coming from the public nuget source.

  <ItemGroup>
    <PackageReference Include="MyCompany.Common" Version="1.0.0" />
    <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
  </ItemGroup>

But what if there is a public package with the same name? I tried this, and scarily it works. So in other words, if someone guesses my private package name, the next time someone clones the repo and builds, it's quite likely Visual Studio will fetch the package from the wrong source.

Is there a way to prevent this? I've been reading the Nuget PackageReference docs and the only thing that seems even remotely close might be a Condition:

<PackageReference Include="Newtonsoft.Json" Version="9.0.1" Condition="'$(TargetFramework)' == 'net452'" />

But it looks like this is more to set conditions based on solution/project/system configuration, not package source.

Is there a conditional that can specify the package source? Or is there something else that can specify the nuget source for a particular package?

I think this might be related to this article.


Solution

  • There is an interesting post here

    https://azure.microsoft.com/en-us/resources/3-ways-to-mitigate-risk-using-private-package-feeds/

    I found the most practical way is to go with the lock mode, with which you will have a package.lock.json file like this

    "dependencies": {
        ".NETCoreApp,Version=v5.0": {
          "Newtonsoft.Json": {
            "type": "Direct",
            "requested": "[12.0.1, )",
            "resolved": "12.0.1",
            "contentHash": "pBR3wCgYWZGiaZDYP+HHYnalVnPJlpP1q55qvVb+adrDHmFMDc1NAKio61xTwftK3Pw5h7TZJPJEEVMd6ty8rg=="
          }
        }
      }
    

    The contentHash should secure the package.

    The lock mode can be enabled by

    <PropertyGroup>
        <RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
    </PropertyGroup>