Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Signed NuGet Package Verification Re-enabled for Linux #7688

Closed
richlander opened this issue Aug 9, 2022 · 5 comments
Closed

Signed NuGet Package Verification Re-enabled for Linux #7688

richlander opened this issue Aug 9, 2022 · 5 comments

Comments

@richlander
Copy link
Member

richlander commented Aug 9, 2022

Updated for .NET 8 SDK Preview 4

Signed NuGet Package Verification Re-enabled for Linux

Signed NuGet package verification has been re-enabled for Linux .NET SDK builds with .NET 6 and 7 (with more details and qualification below). This feature is a key part of secure supply chain enablement for .NET. It validates that NuGet packages have not been tampered with, as part of the restore action. The feature was disabled for Linux and macOS .NET SDK builds in April 2021, for both .NET 5 and 6 (.NET 7 didn't yet exist).

The feature has been enabled for Windows builds throughout, and no changes are being made to Windows behavior. We are not re-enabling NuGet package verification for macOS at this time and we do not know when that will change.

Re-enablement on Linux

Signed NuGet package verification will be enabled by default in .NET 8 SDK Linux builds, starting with Preview 4. It remains opt-in for .NET 7 GA and .NET 6 SDK (6.0.400) builds.

You can opt-in to the feature with the following environment variable, set to true:

DOTNET_NUGET_SIGNATURE_VERIFICATION=true

With .NET 8 SDK Preview 4, you can use the same environment variable to opt-out by setting the variable to false. We have not decided how long we will retain the ability to opt-out. If you need to use it, we would appreciate feedback on why you needed to do that. It might be an issue we need to address.

The following commands were never disabled:

  • dotnet nuget sign
  • dotnet nuget verify

They will produce correct results on Linux with these new builds. With earlier builds, they would not produce reliably correct results.

High-level technical overview

We enabled signed NuGet package verification as part of the .NET 5 release. It included a design flaw that led to the April 2021 incident. The updates in .NET 6, 7, and 8 resolve that flaw.

NuGet signed package verification requires information about certificate roots in order to function. On Linux, we relied on the certificates delivered via the ca-certificates package. This package (to date) only includes certificates that can be trusted for TLS (which is required for HTTPS web usage). It cannot be (correctly) used for code signing and timestamping. However, that's how NuGet was using it for signed package verification.

An industry group decided that the Symantec certificate authority should be distrusted for TLS. No matching decision was made for code signing and timestamping for Symantec-issued certificates. However, we were (incorrectly) using TLS certs on Linux and macOS, so NuGet signed package verification was affected by this distrust decision. As Symantec distrust changes were made in the ca-certificate package in various Linux distros, dotnet restore broke. We saw a similar story unfold on macOS. That's what led to the signed NuGet package verification feature being disabled.

That led us to search for a source of code signing and timestamping certificate roots that we could use cross-platform. We learned that Windows is the only operating system that offers general-purpose code-signing. Our peers at Microsoft agreed to let us redistribute Microsoft code signing and timestamping certificates for .NET to use. That was very nice of them.

The Microsoft code-signing certificates are sourced from and governed by the Microsoft Trusted Root Program. They release updates regularly. At present, we are distributing a code signing and timestamping certificate bundle the dotnet/sdk repo.

The Fedora and Red Hat Enterprise Linux are also starting to use this certificate bundle. From a system perspective, it is much better to distribute these certificates via the ca-certificates package.

With the certificates in place, we came up with the following plan:

  • The .NET SDK will include certificate bundles for both code signing and time stamping.
  • The certificate bundles will be updated monthly, delivered with new SDK versions.
  • Customers will need to install newer (monthly) .NET SDK builds to get updated certificate bundles.
  • The .NET SDK certificate bundles will only be used as a fallback if appropriate operating system certificates are unavailable.
    • On Windows, operating system provided certificates will ALWAYS be used.
    • On Linux, operating system provided certificates will be used if appropriate certificates are provided by ca-certificates.
    • On macOS, no appropriate operating system certificates are available, such that the fallback bundles will ALWAYS be used (if verification is enabled).
  • We are working with Linux distributions to adopt the Microsoft-provided certificate bundles, and distribute via ca-certificates, so that we can use those instead of the .NET SDK-provided fallback bundles.

Note: This plan was designed and reviewed in consultation with various parties, including the Microsoft Trusted Root Program and a subset of Linux distributions who distribute .NET.

macOS status

Signed NuGet package validation is opt-in for both .NET SDK 6.0.4xx and .NET SDK 7.0.1xx on macOS. You can experiment with it, but you will find that it is unusable at this time.

The primary challenge is that Symantec certificates are distrusted on macOS. A Symantec timestamping certificate was used pervasively for signing NuGet packages (since the feature was enabled). .NET relies on macOS certificate APIs for loading certificates, which unfortunately override any trust decisions that we may want to make for Symantec root certificates. The combination of the pervasive Symantec certificate use and its (mandatory) distrust results in NuGet package verification being unusable on macOS (every package fails verification).

We have talked to Apple about this issue, but have been unable to collectively resolve it. That may change at a later time.

We are in the process of moving to a new timestamp signing certificate for NuGet packages. After that is in place, we'll start to encourage top package owners (particularly for popular .NET Foundation and Microsoft packages) to push updates, which will result in the latest packages being signed with a different timestamping certificate and passing verification on macOS. We'll post an announcement on this process at a later time.

If you are a package owner and are using a Symantec-issued certificate for package signing or time-stamping, please acquire a certificate from a different certificate authority now.

Note: One might reasonably expect that we would have moved off the Symantec timestamping certificate a year ago. We planned to do that multiple months ago, but ran into unexpected challenges (also on macOS) with that plan and needed to re-assess. Those unexpected challenges cost us a lot of time.

More information

We've written extensively on this topic. You can learn more from those issues and documents.

@dtivel
Copy link

dtivel commented Aug 26, 2022

In a delay of plans, signed package verification during restore operations will remain disabled by default in .NET 6.0.400 SDK and .NET 7 RC1+ SDK on Linux. It was briefly enabled by default in .NET 6.0.400 SDK containers and in .NET 7 RC1 SDK pre-release builds, but we have since disabled it by default. During these brief and limited re-enablements, we learned that the single certificate bundle in the .NET SDK is inadequate for broad feature re-enablement on Linux and are working on a plan to resolve this in a future .NET SDK release (TBD).

Note that opt-in is still possible, and we appreciate any feedback on this feature.

@dtivel
Copy link

dtivel commented Jan 18, 2023

Updated for .NET 8 SDK Preview 1.

@dtivel
Copy link

dtivel commented May 1, 2023

Updated for .NET 8 SDK Preview 4.

@richlander
Copy link
Member Author

@richlander
Copy link
Member Author

This feature is on its way to shipping to closing this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants