sdk: [Preview] Unable to restore packages from feeds with encrypted passwords on windows

Describe the bug

After the recent update of VS Preview (I got the telemetry prompt earlier today), I’m not able to restore packages from feeds that use an encrypted password.

To Reproduce

  • Make sure some password-protected feeds are registered and they use encrypted password
  • Prepare a project that requests something from the feed
  • Run dotnet nuget locals all --clear just in case to make sure the restore operation is needed
  • Run dotnet restore

Exceptions (if any)

  Retrying 'FindPackagesByIdAsyncCore' for source 'https://nuget.xyz.com/repository/nuget-prod/FindPackagesById()?id='Package'&semVerLevel=2.0.0'.
  Password decryption is not supported on .NET Core for this platform. The following feed uses an encrypted password: 'repo-name'. You can use a clear text password as a workaround.
    Windows Data Protection API (DPAPI) is not supported on this platform.

Detailed exception.

Further technical details

  • Windows 10 21H2
  • SDK 6.0.200-preview.21617.4

Workaround

Use global.json and downgrade to 6.0.100.

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 42
  • Comments: 64 (10 by maintainers)

Commits related to this issue

Most upvoted comments

I debugged this issue with dotnet restore -v diag command. Here is the most inner exception in the stack trace:

System.PlatformNotSupportedException: Windows Data Protection API (DPAPI) is not supported on this platform.
    at System.Security.Cryptography.ProtectedData.Unprotect(Byte[] encryptedData, Byte[] optionalEntropy, DataProtectionScope scope)
    at NuGet.Configuration.EncryptionUtility.DecryptString(String encryptedString)
    at NuGet.Configuration.PackageSourceCredential.get_Password()

So the problem seems to be the System.Security.Cryptography.ProtectedData.dll. The dotnet installation contains the non platform specific version of the DLL at the root level (C:\Program Files\dotnet\sdk\6.0.200\System.Security.Cryptography.ProtectedData.dll). The implementation of this DLL just throws the System.PlatformNotSupportedException since the ProtectedData is only supported on Windows platform.

The Windows platform specific DLL is found under the runtimes directory (C:\Program Files\dotnet\sdk\6.0.200\runtimes\win\lib\netstandard2.0\System.Security.Cryptography.ProtectedData.dll).

For some reason the dotnet executable is using the non platform specific version of the DLL and not the Windows platform specific version.

I was able to workaround the issue by removing the non platform specific DLL at C:\Program Files\dotnet\sdk\6.0.200\System.Security.Cryptography.ProtectedData.dll. After this, the dotnet started using the correct one from C:\Program Files\dotnet\sdk\6.0.200\runtimes\win\lib\netstandard2.0\System.Security.Cryptography.ProtectedData.dll and restore started working again.

EDIT: Environment where I tested is Windows Server 2016.

The MSBuild-side revert is merged to daily builds of the 6.0.2xx SDK, and the next patch release of the .NET SDK should have the fix.

The same issue on multiple environments after today’s update to 6.0.2 from stable channel. One would expect that the platform sharing the same name with Windows Data Protection API would actually be supported 👀

@saurla we’ve said very similar things in meetings this morning 😃 The longer-term plan will require (at minimum):

  • msbuild assembly loading to learn about using deps.json files in a manner similar to the runtime (tracked by https://github.com/dotnet/msbuild/issues/4081)
  • SDK work to enable publishing deps.json files for libraries, not just executables, and flowing those through the build (this appears to already exist in the form of <EnableDynamicLoading>true</EnableDynamicLoading>, which creates the required *.deps.json files)

So over the next couple days we’ll be logging/referencing those work items.

Does anyone know if this issue is mitigated in .NET 6.0.3? I can’t find anything about it in the release notes.

We have the same problem. All projects currently not building on our OnPremise Build-Servers

Just tested .NET SDK 6.0.202 and everything appears to be in order in this version 😉.

We are also seeing this issue in our on-premises build servers using an authenticated TeamCity feed after installing VS 2022 17.1 build tools.

Is there any ETA when this will be rolled out to the hosted agents?

Okay thanks - we solved it by placing a global.json at the root of the build server file system pinning the SDK version to 6.0.101 as mentioned by some others in the thread. Will keep that version pinned for now then until a later SDK release.

@sunero4 just an FYI: pinning to an older framework will work too but you will not be able to benefit from the patches released in the latest SDK. 6.0.201 addresses a couple of critical CVEs: https://github.com/dotnet/core/blob/main/release-notes/6.0/6.0.3/6.0.3.md?WT.mc_id=dotnet-35129-website#notable-changes

Same for us since updating to SDK 6.0.200 (not preview) on our development machines. When I switch back to 6.0.101 it works. Don’t have 6.0.102 to test against (and don’t want to install), so it definitely happened between 6.0.101 and 6.0.200.

Yes it does. .NET SDKs 6.0.104 and 6.0.202 will also include the fix. Updating VS 2022 to 17.1.4 will also pull the needed version.

I just removed the global.json pinning everywhere.

@ABAG603 I’m not sure if it’s sufficient in all cases. Our global.json looks like this:

{
    "sdk": {
        "version": "6.0.101",
        "rollForward": "disable",
        "allowPrerelease": false
    }
}

@MrBjorn no need to change your build scripts. Just install 6.0.101 on all of your build servers and pin it by adding global.json to the root of your repo. { "sdk": { "version": "6.0.101" } }

Important note to everyone. Remove the old Sdk from the global.json when this bug is crushed 😃

You can throw the global.json for pinning the SDK version into any folder up to the root. It will use the first one it finds searching folder-wise upwards from the project directory until it finds the first one. So as long as not every project has already one, feel free to put it into a common parent to force it for all projects at once.

For our Bamboo build server, we just put it directly into the home directory of Bamboo (not even anywhere near to the xml-data folder where the stuff will be checked out).

Just wanted to add my 2 cents: this has made it extremely painful to build software over the last little while for me (when I upgraded VS to 17.1.0). Is there a system-wide workaround, currently I’m just forcing SDK version in each project.

Not sure about others, but this only happens to me when I run nuget add source, and my (very temporary) workaround is to add --store-password-in-clear-text to each nuget add source line. I won’t go into why this was my only option today, but wanted to throw this out there.

I started looking again through the assembly loading trace I pasted in comment https://github.com/dotnet/sdk/issues/23498#issuecomment-1047558751. I noticed that the used AssemblyLoadContext is MSBuildLoadContext. That lead me to think that maybe the problem could be at the MSBuild side instead. I noticed that SDK 6.0.200 uses MSBuild version 17.1.0 and SDK 6.0.101 uses version 17.0.0. I tried to replace MSBuild DLL files of 6.0.200 with the ones from 6.0.101 and the dotnet restore started working. So maybe the problem is in the MSBuild side instead?

I noticed that in the MSBuild side there was this one change between 17.0.0 and 17.1.0 to the MSBuildLoadContext https://github.com/dotnet/msbuild/commit/3bb10b76c5a345b30d6bf55facacbbce47446358. There the version comparison was changed from exact match to exact or greater. The MSBuild depends on version 4.0.2 of System.Security.Cryptography.ProtectedData.dll but dotnet SDK depends on version 5.0.0. So the version present in the SDK is 5.0.0. In previous versions of MSBuildLoadContext the version of System.Security.Cryptography.ProtectedData.dll would not have matched and DLL would not have been loaded from the same folder where MSBuild.dll is located. But in the new version it will load that one. This is just a theory as I’m not on expert when it comes to how assembly loading in .NET works. I do not have a development environment for SDK and MSBuild so that I could test if reverting this change would fix the problem.

I’m getting the same error after installing dotnet 6.0.2 via chocolatey (choco install dotnet-sdk).