NET, .NET Framework, and Visual Studio Security Feature Bypass Vulnerability
Description
NET, .NET Framework, and Visual Studio Security Feature Bypass Vulnerability
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
A logic flaw in .NET's X.509 chain building allows an attacker to bypass certificate validation by presenting a malformed signature, potentially leading to authentication subversion.
Vulnerability
Overview CVE-2024-0057 is a security feature bypass vulnerability in .NET, .NET Framework, and Visual Studio, specifically in the X.509 chain building APIs. Due to a logic flaw, when an application attempts to build a certificate chain using a certificate with a malformed signature, the framework correctly reports that chain building failed, but returns an incorrect reason code. [3] This can cause applications that rely on the reason code for trust decisions to inadvertently treat the failed chain as successful. [1]
Exploitation
An attacker can exploit this vulnerability by presenting an arbitrary untrusted certificate with malformed signatures to an affected application. [3] No special privileges are required; the attacker only needs to be able to supply a certificate to the application. The flawed return of an incorrect reason code (e.g., returning NoErrors instead of a failure flag) allows the application to bypass its own certificate validation logic.
Impact
Successful exploitation could allow an attacker to subvert the application's authentication logic, potentially leading to unauthorized access or other security breaches. [2] The vulnerability affects NuGet packages (NuGet.exe, NuGet.CommandLine, NuGet.Packaging) and .NET SDKs (6.0, 7.0, 8.0) prior to specific patch versions.
Mitigation
Microsoft has released patches for affected .NET SDKs and NuGet packages. [3] Users should update to the latest versions: .NET SDK 6.0.127 or later, 7.0.116 or later, 8.0.102 or later, and corresponding NuGet versions. [2] The fix ensures that the correct revocation status flag is returned, preventing the bypass.
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
NuGet.CommandLineNuGet | >= 4.6.0, < 5.11.6 | 5.11.6 |
NuGet.PackagingNuGet | >= 4.6.0, < 5.11.6 | 5.11.6 |
NuGet.CommandLineNuGet | >= 6.0.0, < 6.0.6 | 6.0.6 |
NuGet.PackagingNuGet | >= 6.0.0, < 6.0.6 | 6.0.6 |
NuGet.CommandLineNuGet | >= 6.3.0, < 6.3.4 | 6.3.4 |
NuGet.PackagingNuGet | >= 6.3.0, < 6.3.4 | 6.3.4 |
NuGet.CommandLineNuGet | >= 6.4.0, < 6.4.3 | 6.4.3 |
NuGet.PackagingNuGet | >= 6.4.0, < 6.4.3 | 6.4.3 |
NuGet.CommandLineNuGet | >= 6.6.0, < 6.6.2 | 6.6.2 |
NuGet.PackagingNuGet | >= 6.6.0, < 6.6.2 | 6.6.2 |
NuGet.CommandLineNuGet | >= 6.7.0, < 6.7.1 | 6.7.1 |
NuGet.PackagingNuGet | >= 6.7.0, < 6.7.1 | 6.7.1 |
NuGet.CommandLineNuGet | >= 6.8.0, < 6.8.1 | 6.8.1 |
NuGet.PackagingNuGet | >= 6.8.0, < 6.8.1 | 6.8.1 |
Affected products
93- osv-coords71 versionspkg:apk/chainguard/aspnet-6-runtimepkg:apk/chainguard/aspnet-6-runtime-defaultpkg:apk/chainguard/aspnet-6-targeting-packpkg:apk/chainguard/aspnet-7-runtimepkg:apk/chainguard/aspnet-7-runtime-defaultpkg:apk/chainguard/aspnet-7-targeting-packpkg:apk/chainguard/dotnet-6pkg:apk/chainguard/dotnet-6-runtimepkg:apk/chainguard/dotnet-6-runtime-defaultpkg:apk/chainguard/dotnet-6-sdkpkg:apk/chainguard/dotnet-6-sdk-defaultpkg:apk/chainguard/dotnet-6-targeting-packpkg:apk/chainguard/dotnet-7pkg:apk/chainguard/dotnet-7-runtimepkg:apk/chainguard/dotnet-7-runtime-defaultpkg:apk/chainguard/dotnet-7-sdkpkg:apk/chainguard/dotnet-7-sdk-defaultpkg:apk/chainguard/dotnet-7-targeting-packpkg:apk/wolfi/aspnet-6-runtimepkg:apk/wolfi/aspnet-6-runtime-defaultpkg:apk/wolfi/aspnet-6-targeting-packpkg:apk/wolfi/aspnet-7-runtimepkg:apk/wolfi/aspnet-7-runtime-defaultpkg:apk/wolfi/aspnet-7-targeting-packpkg:apk/wolfi/dotnet-6pkg:apk/wolfi/dotnet-6-runtimepkg:apk/wolfi/dotnet-6-runtime-defaultpkg:apk/wolfi/dotnet-6-sdkpkg:apk/wolfi/dotnet-6-sdk-defaultpkg:apk/wolfi/dotnet-6-targeting-packpkg:apk/wolfi/dotnet-7pkg:apk/wolfi/dotnet-7-runtimepkg:apk/wolfi/dotnet-7-runtime-defaultpkg:apk/wolfi/dotnet-7-sdkpkg:apk/wolfi/dotnet-7-sdk-defaultpkg:apk/wolfi/dotnet-7-targeting-packpkg:bitnami/dotnetpkg:bitnami/dotnet-sdkpkg:bitnami/powershellpkg:nuget/nuget.commandlinepkg:nuget/nuget.packagingpkg:rpm/almalinux/aspnetcore-runtime-6.0pkg:rpm/almalinux/aspnetcore-runtime-7.0pkg:rpm/almalinux/aspnetcore-runtime-8.0pkg:rpm/almalinux/aspnetcore-targeting-pack-6.0pkg:rpm/almalinux/aspnetcore-targeting-pack-7.0pkg:rpm/almalinux/aspnetcore-targeting-pack-8.0pkg:rpm/almalinux/dotnetpkg:rpm/almalinux/dotnet-apphost-pack-6.0pkg:rpm/almalinux/dotnet-apphost-pack-7.0pkg:rpm/almalinux/dotnet-apphost-pack-8.0pkg:rpm/almalinux/dotnet-hostpkg:rpm/almalinux/dotnet-hostfxr-6.0pkg:rpm/almalinux/dotnet-hostfxr-7.0pkg:rpm/almalinux/dotnet-hostfxr-8.0pkg:rpm/almalinux/dotnet-runtime-6.0pkg:rpm/almalinux/dotnet-runtime-7.0pkg:rpm/almalinux/dotnet-runtime-8.0pkg:rpm/almalinux/dotnet-sdk-6.0pkg:rpm/almalinux/dotnet-sdk-6.0-source-built-artifactspkg:rpm/almalinux/dotnet-sdk-7.0pkg:rpm/almalinux/dotnet-sdk-7.0-source-built-artifactspkg:rpm/almalinux/dotnet-sdk-8.0pkg:rpm/almalinux/dotnet-sdk-8.0-source-built-artifactspkg:rpm/almalinux/dotnet-targeting-pack-6.0pkg:rpm/almalinux/dotnet-targeting-pack-7.0pkg:rpm/almalinux/dotnet-targeting-pack-8.0pkg:rpm/almalinux/dotnet-templates-6.0pkg:rpm/almalinux/dotnet-templates-7.0pkg:rpm/almalinux/dotnet-templates-8.0pkg:rpm/almalinux/netstandard-targeting-pack-2.1
< 6.0.127-r1+ 70 more
- (no CPE)range: < 6.0.127-r1
- (no CPE)range: < 6.0.127-r1
- (no CPE)range: < 6.0.127-r1
- (no CPE)range: < 7.0.116-r0
- (no CPE)range: < 7.0.116-r0
- (no CPE)range: < 7.0.116-r0
- (no CPE)range: < 6.0.127-r1
- (no CPE)range: < 6.0.127-r1
- (no CPE)range: < 6.0.127-r1
- (no CPE)range: < 6.0.127-r1
- (no CPE)range: < 6.0.127-r1
- (no CPE)range: < 6.0.127-r1
- (no CPE)range: < 7.0.116-r0
- (no CPE)range: < 7.0.116-r0
- (no CPE)range: < 7.0.116-r0
- (no CPE)range: < 7.0.116-r0
- (no CPE)range: < 7.0.116-r0
- (no CPE)range: < 7.0.116-r0
- (no CPE)range: < 6.0.127-r1
- (no CPE)range: < 6.0.127-r1
- (no CPE)range: < 6.0.127-r1
- (no CPE)range: < 7.0.116-r0
- (no CPE)range: < 7.0.116-r0
- (no CPE)range: < 7.0.116-r0
- (no CPE)range: < 6.0.127-r1
- (no CPE)range: < 6.0.127-r1
- (no CPE)range: < 6.0.127-r1
- (no CPE)range: < 6.0.127-r1
- (no CPE)range: < 6.0.127-r1
- (no CPE)range: < 6.0.127-r1
- (no CPE)range: < 7.0.116-r0
- (no CPE)range: < 7.0.116-r0
- (no CPE)range: < 7.0.116-r0
- (no CPE)range: < 7.0.116-r0
- (no CPE)range: < 7.0.116-r0
- (no CPE)range: < 7.0.116-r0
- (no CPE)range: >= 6.0.0, < 6.0.26
- (no CPE)range: >= 6.0.0, < 6.0.26
- (no CPE)range: >= 7.2.0, < 7.2.18
- (no CPE)range: >= 4.6.0, < 5.11.6
- (no CPE)range: >= 4.6.0, < 5.11.6
- (no CPE)range: < 6.0.26-1.el9_3
- (no CPE)range: < 7.0.15-1.el9_3
- (no CPE)range: < 8.0.1-1.el8_9
- (no CPE)range: < 6.0.26-1.el9_3
- (no CPE)range: < 7.0.15-1.el9_3
- (no CPE)range: < 8.0.1-1.el8_9
- (no CPE)range: < 8.0.101-1.el8_9
- (no CPE)range: < 6.0.26-1.el9_3
- (no CPE)range: < 7.0.15-1.el9_3
- (no CPE)range: < 8.0.1-1.el8_9
- (no CPE)range: < 8.0.1-1.el8_9
- (no CPE)range: < 6.0.26-1.el9_3
- (no CPE)range: < 7.0.15-1.el9_3
- (no CPE)range: < 8.0.1-1.el8_9
- (no CPE)range: < 6.0.26-1.el9_3
- (no CPE)range: < 7.0.15-1.el9_3
- (no CPE)range: < 8.0.1-1.el8_9
- (no CPE)range: < 6.0.126-1.el9_3
- (no CPE)range: < 6.0.126-1.el9_3
- (no CPE)range: < 7.0.115-1.el9_3
- (no CPE)range: < 7.0.115-1.el9_3
- (no CPE)range: < 8.0.101-1.el8_9
- (no CPE)range: < 8.0.101-1.el8_9
- (no CPE)range: < 6.0.26-1.el9_3
- (no CPE)range: < 7.0.15-1.el9_3
- (no CPE)range: < 8.0.1-1.el8_9
- (no CPE)range: < 6.0.126-1.el9_3
- (no CPE)range: < 7.0.115-1.el9_3
- (no CPE)range: < 8.0.101-1.el8_9
- (no CPE)range: < 8.0.101-1.el8_9
- Microsoft/Microsoft .NET Framework 2.0 Service Pack 2v5Range: 2.0.0
- Microsoft/Microsoft .NET Framework 3.0 Service Pack 2v5Range: 3.0.0
- Microsoft/Microsoft .NET Framework 3.5 AND 4.7.2v5Range: 4.7.0
- Microsoft/Microsoft .NET Framework 3.5 AND 4.8v5Range: 4.8.0
- Microsoft/Microsoft .NET Framework 3.5 AND 4.8.1v5Range: 4.8.1
- Microsoft/Microsoft .NET Framework 4.6.2/4.7/4.7.1/4.7.2v5Range: 4.7.0
- Microsoft/Microsoft .NET Framework 4.8v5Range: 4.8.0
- Microsoft/Microsoft Visual Studio 2019 version 16.11 (includes 16.0 - 16.10)v5Range: 16.11.0
- Microsoft/Microsoft Visual Studio 2022 version 17.2v5Range: 17.2.0
- Microsoft/Microsoft Visual Studio 2022 version 17.4v5Range: 17.4.0
- Microsoft/Microsoft Visual Studio 2022 version 17.6v5Range: 17.6.0
- Microsoft/Microsoft Visual Studio 2022 version 17.8v5Range: 17.8.0
- Microsoft/.NET 6.0v5Range: 6.0.0
- Microsoft/.NET 7.0v5Range: 7.0.0
- Microsoft/.NET 8.0v5Range: 8.0
- Microsoft/NuGet 17.4.0v5Range: 17.4.0
- Microsoft/NUGET 17.6.0v5Range: 17.6.0
- Microsoft/NuGet 17.8.0v5Range: 17.8.0
- Microsoft/NuGet 5.11.0v5Range: 5.11.0
- Microsoft/PowerShell 7.2v5Range: 7.2.0
- Microsoft/PowerShell 7.3v5Range: 7.3.0
- Microsoft/PowerShell 7.4v5Range: 7.4.0
Patches
25e1ba955cca1Merged PR 502035: Handle no error status in chain
11 files changed · +57 −27
src/NuGet.Core/NuGet.Packaging/PublicAPI/net472/PublicAPI.Shipped.txt+2 −1 modified@@ -1102,8 +1102,9 @@ NuGet.Packaging.Signing.SignatureVerificationStatusFlags.NoValidTimestamp = 1310 NuGet.Packaging.Signing.SignatureVerificationStatusFlags.SignatureAlgorithmUnsupported = 16 -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags NuGet.Packaging.Signing.SignatureVerificationStatusFlags.SignatureCheckFailed = 8 -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags NuGet.Packaging.Signing.SignatureVerificationStatusFlags.Suspect = NuGet.Packaging.Signing.SignatureVerificationStatusFlags.IntegrityCheckFailed | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.CertificateRevoked -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags +NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UnknownBuildStatus = 524288 -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UnknownRevocation = 8192 -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags -NuGet.Packaging.Signing.SignatureVerificationStatusFlags.Untrusted = NuGet.Packaging.Signing.SignatureVerificationStatusFlags.NoSignature | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.CertificateExpired | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.ChainBuildingFailure | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UnknownRevocation | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UntrustedRoot | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.GeneralizedTimeOutsideValidity -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags +NuGet.Packaging.Signing.SignatureVerificationStatusFlags.Untrusted = NuGet.Packaging.Signing.SignatureVerificationStatusFlags.NoSignature | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.CertificateExpired | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.ChainBuildingFailure | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UnknownRevocation | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UntrustedRoot | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.GeneralizedTimeOutsideValidity | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UnknownBuildStatus -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UntrustedRoot = 32768 -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags NuGet.Packaging.Signing.SignatureVerificationSummary NuGet.Packaging.Signing.SignatureVerificationSummary.ExpirationTime.get -> System.DateTimeOffset?
src/NuGet.Core/NuGet.Packaging/PublicAPI/netcoreapp5.0/PublicAPI.Shipped.txt+2 −1 modified@@ -1089,8 +1089,9 @@ NuGet.Packaging.Signing.SignatureVerificationStatusFlags.NoValidTimestamp = 1310 NuGet.Packaging.Signing.SignatureVerificationStatusFlags.SignatureAlgorithmUnsupported = 16 -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags NuGet.Packaging.Signing.SignatureVerificationStatusFlags.SignatureCheckFailed = 8 -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags NuGet.Packaging.Signing.SignatureVerificationStatusFlags.Suspect = NuGet.Packaging.Signing.SignatureVerificationStatusFlags.IntegrityCheckFailed | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.CertificateRevoked -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags +NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UnknownBuildStatus = 524288 -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UnknownRevocation = 8192 -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags -NuGet.Packaging.Signing.SignatureVerificationStatusFlags.Untrusted = NuGet.Packaging.Signing.SignatureVerificationStatusFlags.NoSignature | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.CertificateExpired | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.ChainBuildingFailure | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UnknownRevocation | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UntrustedRoot | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.GeneralizedTimeOutsideValidity -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags +NuGet.Packaging.Signing.SignatureVerificationStatusFlags.Untrusted = NuGet.Packaging.Signing.SignatureVerificationStatusFlags.NoSignature | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.CertificateExpired | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.ChainBuildingFailure | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UnknownRevocation | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UntrustedRoot | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.GeneralizedTimeOutsideValidity | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UnknownBuildStatus -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UntrustedRoot = 32768 -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags NuGet.Packaging.Signing.SignatureVerificationSummary NuGet.Packaging.Signing.SignatureVerificationSummary.ExpirationTime.get -> System.DateTimeOffset?
src/NuGet.Core/NuGet.Packaging/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt+2 −1 modified@@ -1069,8 +1069,9 @@ NuGet.Packaging.Signing.SignatureVerificationStatusFlags.NoValidTimestamp = 1310 NuGet.Packaging.Signing.SignatureVerificationStatusFlags.SignatureAlgorithmUnsupported = 16 -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags NuGet.Packaging.Signing.SignatureVerificationStatusFlags.SignatureCheckFailed = 8 -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags NuGet.Packaging.Signing.SignatureVerificationStatusFlags.Suspect = NuGet.Packaging.Signing.SignatureVerificationStatusFlags.IntegrityCheckFailed | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.CertificateRevoked -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags +NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UnknownBuildStatus = 524288 -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UnknownRevocation = 8192 -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags -NuGet.Packaging.Signing.SignatureVerificationStatusFlags.Untrusted = NuGet.Packaging.Signing.SignatureVerificationStatusFlags.NoSignature | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.CertificateExpired | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.ChainBuildingFailure | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UnknownRevocation | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UntrustedRoot | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.GeneralizedTimeOutsideValidity -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags +NuGet.Packaging.Signing.SignatureVerificationStatusFlags.Untrusted = NuGet.Packaging.Signing.SignatureVerificationStatusFlags.NoSignature | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.CertificateExpired | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.ChainBuildingFailure | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UnknownRevocation | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UntrustedRoot | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.GeneralizedTimeOutsideValidity | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UnknownBuildStatus -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UntrustedRoot = 32768 -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags NuGet.Packaging.Signing.SignatureVerificationSummary NuGet.Packaging.Signing.SignatureVerificationSummary.ExpirationTime.get -> System.DateTimeOffset?
src/NuGet.Core/NuGet.Packaging/Signing/Signatures/Signature.cs+12 −9 modified@@ -144,7 +144,6 @@ public virtual SignatureVerificationSummary Verify( X509Certificate2Collection certificateExtraStore) { settings = settings ?? SignatureVerifySettings.Default; - var flags = SignatureVerificationStatusFlags.NoErrors; var issues = new List<SignatureLog>(); SignatureVerificationStatus status; @@ -153,10 +152,8 @@ public virtual SignatureVerificationSummary Verify( { issues.Add(SignatureLog.Issue(!settings.AllowIllegal, NuGetLogCode.NU3010, string.Format(CultureInfo.CurrentCulture, Strings.Verify_ErrorNoCertificate, FriendlyName))); - flags |= SignatureVerificationStatusFlags.NoCertificate; status = settings.AllowIllegal ? SignatureVerificationStatus.Valid : SignatureVerificationStatus.Disallowed; - - return new SignatureVerificationSummary(Type, status, flags, issues); + return new SignatureVerificationSummary(Type, status, SignatureVerificationStatusFlags.NoCertificate, issues); } issues.Add(SignatureLog.InformationLog(string.Format(CultureInfo.CurrentCulture, @@ -175,21 +172,22 @@ public virtual SignatureVerificationSummary Verify( { issues.Add(SignatureLog.Issue(!settings.AllowIllegal, NuGetLogCode.NU3012, string.Format(CultureInfo.CurrentCulture, Strings.VerifyError_SignatureVerificationFailed, FriendlyName))); issues.Add(SignatureLog.DebugLog(e.ToString())); - flags |= SignatureVerificationStatusFlags.SignatureCheckFailed; status = settings.AllowIllegal ? SignatureVerificationStatus.Valid : SignatureVerificationStatus.Disallowed; - return new SignatureVerificationSummary(Type, status, flags, issues); + return new SignatureVerificationSummary(Type, status, SignatureVerificationStatusFlags.SignatureCheckFailed, issues); } DateTimeOffset? expirationTime = null; var certificateFlags = VerificationUtility.ValidateSigningCertificate(certificate, !settings.AllowIllegal, FriendlyName, issues); if (certificateFlags != SignatureVerificationStatusFlags.NoErrors) { - flags |= certificateFlags; + status = VerificationUtility.GetSignatureVerificationStatus(certificateFlags); + return new SignatureVerificationSummary(Type, status, certificateFlags, timestamp, expirationTime, issues); } else { timestamp = timestamp ?? new Timestamp(); + SignatureVerificationStatusFlags flags = SignatureVerificationStatusFlags.NoErrors; using (var chainHolder = new X509ChainHolder()) { var chain = chainHolder.Chain; @@ -218,8 +216,11 @@ public virtual SignatureVerificationSummary Verify( var chainBuildingHasIssues = false; - if (!chainBuildingSucceeded) + if (!chainBuildingSucceeded && chainStatuses.Length == 0) { + return new SignatureVerificationSummary(Type, SignatureVerificationStatus.Unknown, SignatureVerificationStatusFlags.UnknownBuildStatus, timestamp, issues); + } + var statusFlags = CertificateChainUtility.DefaultObservedStatusFlags; IEnumerable<string> messages; @@ -305,6 +306,8 @@ public virtual SignatureVerificationSummary Verify( } } + if (!chainBuildingSucceeded) + { // Debug log any errors issues.Add(SignatureLog.DebugLog( string.Format( @@ -335,12 +338,12 @@ public virtual SignatureVerificationSummary Verify( expirationTime = DateTime.SpecifyKind(certificate.NotAfter, DateTimeKind.Local); } } - } status = VerificationUtility.GetSignatureVerificationStatus(flags); return new SignatureVerificationSummary(Type, status, flags, timestamp, expirationTime, issues); } + } public string GetSigningCertificateFingerprint(HashAlgorithmName algorithm) {
src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Timestamp.cs+18 −11 modified@@ -109,8 +109,6 @@ internal SignatureVerificationStatusFlags Verify( throw new ArgumentNullException(nameof(settings)); } - var flags = SignatureVerificationStatusFlags.NoErrors; - if (signature == null) { throw new ArgumentNullException(nameof(signature)); @@ -124,14 +122,16 @@ internal SignatureVerificationStatusFlags Verify( var timestamperCertificate = SignerInfo.Certificate; if (timestamperCertificate == null) { - flags |= SignatureVerificationStatusFlags.NoCertificate; - issues.Add(SignatureLog.Issue(treatIssueAsError, NuGetLogCode.NU3020, string.Format(CultureInfo.CurrentCulture, Strings.VerifyError_TimestampNoCertificate, signature.FriendlyName))); - return flags; + return SignatureVerificationStatusFlags.NoCertificate; } - flags |= VerificationUtility.ValidateTimestamp(this, signature, treatIssueAsError, issues, SigningSpecifications.V1); - if (flags == SignatureVerificationStatusFlags.NoErrors) + var timestampFlags = VerificationUtility.ValidateTimestamp(this, signature, treatIssueAsError, issues, SigningSpecifications.V1); + if (timestampFlags != SignatureVerificationStatusFlags.NoErrors) + { + return timestampFlags; + } + else { issues.Add(SignatureLog.InformationLog(string.Format(CultureInfo.CurrentCulture, Strings.TimestampValue, GeneralizedTime.LocalDateTime.ToString()) + Environment.NewLine)); @@ -140,6 +140,7 @@ internal SignatureVerificationStatusFlags Verify( signature.FriendlyName, $"{Environment.NewLine}{CertificateUtility.X509Certificate2ToString(timestamperCertificate, fingerprintAlgorithm)}"))); + SignatureVerificationStatusFlags flags = SignatureVerificationStatusFlags.NoErrors; var certificateExtraStore = SignedCms.Certificates; using (var chainHolder = new X509ChainHolder()) @@ -170,9 +171,14 @@ internal SignatureVerificationStatusFlags Verify( if (chainBuildSucceed) { - return flags; + return SignatureVerificationStatusFlags.NoErrors; } - + else if (chainStatusList.Length == 0) + { + return SignatureVerificationStatusFlags.UnknownBuildStatus; + } + else + { var chainBuildingHasIssues = false; IEnumerable<string> messages; @@ -251,12 +257,13 @@ internal SignatureVerificationStatusFlags Verify( if (!chainBuildingHasIssues && (settings.AllowIgnoreTimestamp || settings.AllowUnknownRevocation)) { - return flags; + return SignatureVerificationStatusFlags.NoErrors; } flags |= SignatureVerificationStatusFlags.UnknownRevocation; chainBuildingHasIssues = true; } + } // Debug log any errors issues.Add( @@ -267,10 +274,10 @@ internal SignatureVerificationStatusFlags Verify( Strings.VerifyError_InvalidCertificateChain, string.Join(", ", chainStatusList.Select(x => x.Status.ToString()))))); } - } return flags; } + } #endif } }
src/NuGet.Core/NuGet.Packaging/Signing/Utility/CertificateChainUtility.cs+1 −1 modified@@ -91,7 +91,7 @@ public static IX509CertificateChain GetCertificateChain( } } - if (fatalStatuses.Any()) + if (chain.ChainStatus.Length == 0 || fatalStatuses.Count > 0) { if (certificateType == CertificateType.Timestamp) {
src/NuGet.Core/NuGet.Packaging/Signing/Utility/CertificateUtility.cs+6 −1 modified@@ -325,7 +325,12 @@ public static bool IsSelfIssued(X509Certificate2 certificate) X509VerificationFlags.IgnoreCertificateAuthorityRevocationUnknown | X509VerificationFlags.IgnoreEndRevocationUnknown; - chain.Build(certificate); + bool buildSuccess = chain.Build(certificate); + + if (!buildSuccess && chain.ChainStatus.Length == 0) + { + throw new SignatureException(Strings.CertificateChainValidationFailed); + } if (chain.ChainElements.Count != 1) {
src/NuGet.Core/NuGet.Packaging/Signing/Utility/SignatureUtility.cs+5 −1 modified@@ -625,7 +625,11 @@ private static IX509CertificateChain GetCertificateChain( chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; - chain.Build(certificate); + bool buildSuccess = chain.Build(certificate); + if (!buildSuccess && chain.ChainStatus.Length == 0) + { + throw new SignatureException(Strings.CertificateChainValidationFailed); + } if (chain.ChainStatus.Any(chainStatus => chainStatus.Status.HasFlag(X509ChainStatusFlags.Cyclic) ||
src/NuGet.Core/NuGet.Packaging/Signing/Verification/SignatureVerificationStatusFlags.cs+7 −1 modified@@ -110,6 +110,11 @@ public enum SignatureVerificationStatusFlags /// </summary> MultipleTimestamps = 1 << 18, + /// <summary> + /// Unknown build status. + /// </summary> + UnknownBuildStatus = 1 << 19, + /// <summary> /// Flags which indicate that the signed package is suspect. /// </summary> @@ -137,6 +142,7 @@ public enum SignatureVerificationStatusFlags ChainBuildingFailure | UnknownRevocation | UntrustedRoot | - GeneralizedTimeOutsideValidity + GeneralizedTimeOutsideValidity | + UnknownBuildStatus } }
test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/SignatureVerificationStatusFlagsTests.cs+1 −0 modified@@ -42,6 +42,7 @@ public void EnumDefintion_HasNotChangedUnexpectedly() { "GeneralizedTimeOutsideValidity", 1 << 16 }, { "NoValidTimestamp", 1 << 17 }, { "MultipleTimestamps", 1 << 18 }, + { "UnknownBuildStatus", 1 << 19 }, { "Suspect", (int)(SignatureVerificationStatusFlags.IntegrityCheckFailed | SignatureVerificationStatusFlags.CertificateRevoked) }, { "Illegal", (int)(SignatureVerificationStatusFlags.NoCertificate |
test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/VerificationUtilityTests.cs+1 −0 modified@@ -33,6 +33,7 @@ public class VerificationUtilityTests [InlineData(SignatureVerificationStatusFlags.Suspect, SignatureVerificationStatus.Suspect)] [InlineData(SignatureVerificationStatusFlags.Illegal, SignatureVerificationStatus.Disallowed)] [InlineData(SignatureVerificationStatusFlags.Untrusted, SignatureVerificationStatus.Disallowed)] + [InlineData(SignatureVerificationStatusFlags.UnknownBuildStatus, SignatureVerificationStatus.Unknown)] public void GetSignatureVerificationStatus_WithStatusFlag_ReturnsStatus( SignatureVerificationStatusFlags flags, SignatureVerificationStatus expectedStatus)
3333f352ec47Merged PR 502035: Handle no error status in chain
11 files changed · +185 −154
src/NuGet.Core/NuGet.Packaging/PublicAPI/net472/PublicAPI.Shipped.txt+2 −1 modified@@ -1103,8 +1103,9 @@ NuGet.Packaging.Signing.SignatureVerificationStatusFlags.NoValidTimestamp = 1310 NuGet.Packaging.Signing.SignatureVerificationStatusFlags.SignatureAlgorithmUnsupported = 16 -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags NuGet.Packaging.Signing.SignatureVerificationStatusFlags.SignatureCheckFailed = 8 -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags NuGet.Packaging.Signing.SignatureVerificationStatusFlags.Suspect = NuGet.Packaging.Signing.SignatureVerificationStatusFlags.IntegrityCheckFailed | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.CertificateRevoked -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags +NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UnknownBuildStatus = 524288 -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UnknownRevocation = 8192 -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags -NuGet.Packaging.Signing.SignatureVerificationStatusFlags.Untrusted = NuGet.Packaging.Signing.SignatureVerificationStatusFlags.NoSignature | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.CertificateExpired | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.ChainBuildingFailure | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UnknownRevocation | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UntrustedRoot | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.GeneralizedTimeOutsideValidity -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags +NuGet.Packaging.Signing.SignatureVerificationStatusFlags.Untrusted = NuGet.Packaging.Signing.SignatureVerificationStatusFlags.NoSignature | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.CertificateExpired | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.ChainBuildingFailure | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UnknownRevocation | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UntrustedRoot | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.GeneralizedTimeOutsideValidity | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UnknownBuildStatus -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UntrustedRoot = 32768 -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags NuGet.Packaging.Signing.SignatureVerificationSummary NuGet.Packaging.Signing.SignatureVerificationSummary.ExpirationTime.get -> System.DateTimeOffset?
src/NuGet.Core/NuGet.Packaging/PublicAPI/netcoreapp5.0/PublicAPI.Shipped.txt+2 −1 modified@@ -1090,8 +1090,9 @@ NuGet.Packaging.Signing.SignatureVerificationStatusFlags.NoValidTimestamp = 1310 NuGet.Packaging.Signing.SignatureVerificationStatusFlags.SignatureAlgorithmUnsupported = 16 -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags NuGet.Packaging.Signing.SignatureVerificationStatusFlags.SignatureCheckFailed = 8 -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags NuGet.Packaging.Signing.SignatureVerificationStatusFlags.Suspect = NuGet.Packaging.Signing.SignatureVerificationStatusFlags.IntegrityCheckFailed | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.CertificateRevoked -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags +NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UnknownBuildStatus = 524288 -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UnknownRevocation = 8192 -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags -NuGet.Packaging.Signing.SignatureVerificationStatusFlags.Untrusted = NuGet.Packaging.Signing.SignatureVerificationStatusFlags.NoSignature | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.CertificateExpired | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.ChainBuildingFailure | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UnknownRevocation | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UntrustedRoot | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.GeneralizedTimeOutsideValidity -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags +NuGet.Packaging.Signing.SignatureVerificationStatusFlags.Untrusted = NuGet.Packaging.Signing.SignatureVerificationStatusFlags.NoSignature | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.CertificateExpired | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.ChainBuildingFailure | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UnknownRevocation | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UntrustedRoot | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.GeneralizedTimeOutsideValidity | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UnknownBuildStatus -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UntrustedRoot = 32768 -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags NuGet.Packaging.Signing.SignatureVerificationSummary NuGet.Packaging.Signing.SignatureVerificationSummary.ExpirationTime.get -> System.DateTimeOffset?
src/NuGet.Core/NuGet.Packaging/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt+2 −1 modified@@ -1070,8 +1070,9 @@ NuGet.Packaging.Signing.SignatureVerificationStatusFlags.NoValidTimestamp = 1310 NuGet.Packaging.Signing.SignatureVerificationStatusFlags.SignatureAlgorithmUnsupported = 16 -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags NuGet.Packaging.Signing.SignatureVerificationStatusFlags.SignatureCheckFailed = 8 -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags NuGet.Packaging.Signing.SignatureVerificationStatusFlags.Suspect = NuGet.Packaging.Signing.SignatureVerificationStatusFlags.IntegrityCheckFailed | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.CertificateRevoked -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags +NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UnknownBuildStatus = 524288 -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UnknownRevocation = 8192 -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags -NuGet.Packaging.Signing.SignatureVerificationStatusFlags.Untrusted = NuGet.Packaging.Signing.SignatureVerificationStatusFlags.NoSignature | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.CertificateExpired | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.ChainBuildingFailure | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UnknownRevocation | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UntrustedRoot | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.GeneralizedTimeOutsideValidity -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags +NuGet.Packaging.Signing.SignatureVerificationStatusFlags.Untrusted = NuGet.Packaging.Signing.SignatureVerificationStatusFlags.NoSignature | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.CertificateExpired | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.ChainBuildingFailure | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UnknownRevocation | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UntrustedRoot | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.GeneralizedTimeOutsideValidity | NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UnknownBuildStatus -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags NuGet.Packaging.Signing.SignatureVerificationStatusFlags.UntrustedRoot = 32768 -> NuGet.Packaging.Signing.SignatureVerificationStatusFlags NuGet.Packaging.Signing.SignatureVerificationSummary NuGet.Packaging.Signing.SignatureVerificationSummary.ExpirationTime.get -> System.DateTimeOffset?
src/NuGet.Core/NuGet.Packaging/Signing/Signatures/Signature.cs+80 −77 modified@@ -144,7 +144,6 @@ public virtual SignatureVerificationSummary Verify( X509Certificate2Collection certificateExtraStore) { settings = settings ?? SignatureVerifySettings.Default; - var flags = SignatureVerificationStatusFlags.NoErrors; var issues = new List<SignatureLog>(); SignatureVerificationStatus status; @@ -153,10 +152,8 @@ public virtual SignatureVerificationSummary Verify( { issues.Add(SignatureLog.Issue(!settings.AllowIllegal, NuGetLogCode.NU3010, string.Format(CultureInfo.CurrentCulture, Strings.Verify_ErrorNoCertificate, FriendlyName))); - flags |= SignatureVerificationStatusFlags.NoCertificate; status = settings.AllowIllegal ? SignatureVerificationStatus.Valid : SignatureVerificationStatus.Disallowed; - - return new SignatureVerificationSummary(Type, status, flags, issues); + return new SignatureVerificationSummary(Type, status, SignatureVerificationStatusFlags.NoCertificate, issues); } issues.Add(SignatureLog.InformationLog(string.Format(CultureInfo.CurrentCulture, @@ -175,21 +172,22 @@ public virtual SignatureVerificationSummary Verify( { issues.Add(SignatureLog.Issue(!settings.AllowIllegal, NuGetLogCode.NU3012, string.Format(CultureInfo.CurrentCulture, Strings.VerifyError_SignatureVerificationFailed, FriendlyName))); issues.Add(SignatureLog.DebugLog(e.ToString())); - flags |= SignatureVerificationStatusFlags.SignatureCheckFailed; status = settings.AllowIllegal ? SignatureVerificationStatus.Valid : SignatureVerificationStatus.Disallowed; - return new SignatureVerificationSummary(Type, status, flags, issues); + return new SignatureVerificationSummary(Type, status, SignatureVerificationStatusFlags.SignatureCheckFailed, issues); } DateTimeOffset? expirationTime = null; var certificateFlags = VerificationUtility.ValidateSigningCertificate(certificate, !settings.AllowIllegal, FriendlyName, issues); if (certificateFlags != SignatureVerificationStatusFlags.NoErrors) { - flags |= certificateFlags; + status = VerificationUtility.GetSignatureVerificationStatus(certificateFlags); + return new SignatureVerificationSummary(Type, status, certificateFlags, timestamp, expirationTime, issues); } else { timestamp = timestamp ?? new Timestamp(); + SignatureVerificationStatusFlags flags = SignatureVerificationStatusFlags.NoErrors; using (X509ChainHolder chainHolder = X509ChainHolder.CreateForCodeSigning()) { IX509Chain chain = chainHolder.Chain2; @@ -218,102 +216,107 @@ public virtual SignatureVerificationSummary Verify( var chainBuildingHasIssues = false; - if (!chainBuildingSucceeded) + if (!chainBuildingSucceeded && chainStatuses.Length == 0) { - var statusFlags = CertificateChainUtility.DefaultObservedStatusFlags; + return new SignatureVerificationSummary(Type, SignatureVerificationStatus.Unknown, SignatureVerificationStatusFlags.UnknownBuildStatus, timestamp, issues); + } - IEnumerable<string> messages; - if (CertificateChainUtility.TryGetStatusAndMessage(chainStatuses, statusFlags, out messages)) - { - foreach (var message in messages) - { - issues.Add(SignatureLog.Issue(!settings.AllowIllegal, NuGetLogCode.NU3012, string.Format(CultureInfo.CurrentCulture, Strings.VerifyChainBuildingIssue, FriendlyName, message))); - } + var statusFlags = CertificateChainUtility.DefaultObservedStatusFlags; - chainBuildingHasIssues = true; - flags |= SignatureVerificationStatusFlags.ChainBuildingFailure; + IEnumerable<string> messages; + if (CertificateChainUtility.TryGetStatusAndMessage(chainStatuses, statusFlags, out messages)) + { + foreach (var message in messages) + { + issues.Add(SignatureLog.Issue(!settings.AllowIllegal, NuGetLogCode.NU3012, string.Format(CultureInfo.CurrentCulture, Strings.VerifyChainBuildingIssue, FriendlyName, message))); } - // For all the special cases, chain status list only has unique elements for each chain status flag present - // therefore if we are checking for one specific chain status we can use the first of the returned list - // if we are combining checks for more than one, then we have to use the whole list. - if (CertificateChainUtility.TryGetStatusAndMessage(chainStatuses, X509ChainStatusFlags.Revoked, out messages)) + chainBuildingHasIssues = true; + flags |= SignatureVerificationStatusFlags.ChainBuildingFailure; + } + + // For all the special cases, chain status list only has unique elements for each chain status flag present + // therefore if we are checking for one specific chain status we can use the first of the returned list + // if we are combining checks for more than one, then we have to use the whole list. + if (CertificateChainUtility.TryGetStatusAndMessage(chainStatuses, X509ChainStatusFlags.Revoked, out messages)) + { + issues.Add(SignatureLog.Error(NuGetLogCode.NU3012, string.Format(CultureInfo.CurrentCulture, Strings.VerifyChainBuildingIssue, FriendlyName, messages.First()))); + flags |= SignatureVerificationStatusFlags.CertificateRevoked; + + return new SignatureVerificationSummary(Type, SignatureVerificationStatus.Suspect, flags, timestamp, issues); + } + + if (CertificateChainUtility.TryGetStatusAndMessage(chainStatuses, X509ChainStatusFlags.UntrustedRoot, out messages)) + { + if (settings.ReportUntrustedRoot) { - issues.Add(SignatureLog.Error(NuGetLogCode.NU3012, string.Format(CultureInfo.CurrentCulture, Strings.VerifyChainBuildingIssue, FriendlyName, messages.First()))); - flags |= SignatureVerificationStatusFlags.CertificateRevoked; + SignatureUtility.LogAdditionalContext(chain, issues); - return new SignatureVerificationSummary(Type, SignatureVerificationStatus.Suspect, flags, timestamp, issues); + issues.Add(SignatureLog.Issue(!settings.AllowUntrusted, NuGetLogCode.NU3018, string.Format(CultureInfo.CurrentCulture, Strings.VerifyChainBuildingIssue_UntrustedRoot, FriendlyName))); } - if (CertificateChainUtility.TryGetStatusAndMessage(chainStatuses, X509ChainStatusFlags.UntrustedRoot, out messages)) + if (!settings.AllowUntrusted) { - if (settings.ReportUntrustedRoot) - { - SignatureUtility.LogAdditionalContext(chain, issues); + chainBuildingHasIssues = true; + flags |= SignatureVerificationStatusFlags.UntrustedRoot; + } + } - issues.Add(SignatureLog.Issue(!settings.AllowUntrusted, NuGetLogCode.NU3018, string.Format(CultureInfo.CurrentCulture, Strings.VerifyChainBuildingIssue_UntrustedRoot, FriendlyName))); - } + var offlineRevocationErrors = CertificateChainUtility.TryGetStatusAndMessage(chainStatuses, X509ChainStatusFlags.OfflineRevocation, out var _); + var unknownRevocationErrors = CertificateChainUtility.TryGetStatusAndMessage(chainStatuses, X509ChainStatusFlags.RevocationStatusUnknown, out var unknownRevocationStatusMessages); + if (offlineRevocationErrors || unknownRevocationErrors) + { + if (settings.ReportUnknownRevocation) + { + string unknownRevocationMessage = null; - if (!settings.AllowUntrusted) + if (unknownRevocationErrors) { - chainBuildingHasIssues = true; - flags |= SignatureVerificationStatusFlags.UntrustedRoot; + unknownRevocationMessage = string.Format(CultureInfo.CurrentCulture, Strings.VerifyChainBuildingIssue, FriendlyName, unknownRevocationStatusMessages.First()); } - } - var offlineRevocationErrors = CertificateChainUtility.TryGetStatusAndMessage(chainStatuses, X509ChainStatusFlags.OfflineRevocation, out var _); - var unknownRevocationErrors = CertificateChainUtility.TryGetStatusAndMessage(chainStatuses, X509ChainStatusFlags.RevocationStatusUnknown, out var unknownRevocationStatusMessages); - if (offlineRevocationErrors || unknownRevocationErrors) - { - if (settings.ReportUnknownRevocation) + if (settings.RevocationMode == RevocationMode.Offline) { - string unknownRevocationMessage = null; - - if (unknownRevocationErrors) + if (offlineRevocationErrors) { - unknownRevocationMessage = string.Format(CultureInfo.CurrentCulture, Strings.VerifyChainBuildingIssue, FriendlyName, unknownRevocationStatusMessages.First()); + issues.Add(SignatureLog.InformationLog(string.Format(CultureInfo.CurrentCulture, Strings.VerifyChainBuildingIssue, FriendlyName, Strings.VerifyCertTrustOfflineWhileRevocationModeOffline))); } - if (settings.RevocationMode == RevocationMode.Offline) + if (unknownRevocationMessage != null) { - if (offlineRevocationErrors) - { - issues.Add(SignatureLog.InformationLog(string.Format(CultureInfo.CurrentCulture, Strings.VerifyChainBuildingIssue, FriendlyName, Strings.VerifyCertTrustOfflineWhileRevocationModeOffline))); - } - - if (unknownRevocationMessage != null) - { - issues.Add(SignatureLog.InformationLog(unknownRevocationMessage)); - } + issues.Add(SignatureLog.InformationLog(unknownRevocationMessage)); } - else + } + else + { + if (offlineRevocationErrors) { - if (offlineRevocationErrors) - { - issues.Add(SignatureLog.Issue(!settings.AllowUnknownRevocation, NuGetLogCode.NU3018, string.Format(CultureInfo.CurrentCulture, Strings.VerifyChainBuildingIssue, FriendlyName, Strings.VerifyCertTrustOfflineWhileRevocationModeOnline))); - } - - if (unknownRevocationMessage != null) - { - issues.Add(SignatureLog.Issue(!settings.AllowUnknownRevocation, NuGetLogCode.NU3018, unknownRevocationMessage)); - } + issues.Add(SignatureLog.Issue(!settings.AllowUnknownRevocation, NuGetLogCode.NU3018, string.Format(CultureInfo.CurrentCulture, Strings.VerifyChainBuildingIssue, FriendlyName, Strings.VerifyCertTrustOfflineWhileRevocationModeOnline))); } - } - if (!settings.AllowUnknownRevocation) - { - chainBuildingHasIssues = true; - flags |= SignatureVerificationStatusFlags.UnknownRevocation; + if (unknownRevocationMessage != null) + { + issues.Add(SignatureLog.Issue(!settings.AllowUnknownRevocation, NuGetLogCode.NU3018, unknownRevocationMessage)); + } } } + if (!settings.AllowUnknownRevocation) + { + chainBuildingHasIssues = true; + flags |= SignatureVerificationStatusFlags.UnknownRevocation; + } + } + + if (!chainBuildingSucceeded) + { // Debug log any errors issues.Add(SignatureLog.DebugLog( - string.Format( - CultureInfo.CurrentCulture, - Strings.VerifyError_InvalidCertificateChain, - FriendlyName, - string.Join(", ", chainStatuses.Select(x => x.Status.ToString()))))); + string.Format( + CultureInfo.CurrentCulture, + Strings.VerifyError_InvalidCertificateChain, + FriendlyName, + string.Join(", ", chainStatuses.Select(x => x.Status.ToString()))))); } var isSignatureTimeValid = Rfc3161TimestampVerificationUtility.ValidateSignerCertificateAgainstTimestamp(certificate, timestamp); @@ -337,11 +340,11 @@ public virtual SignatureVerificationSummary Verify( expirationTime = DateTime.SpecifyKind(certificate.NotAfter, DateTimeKind.Local); } } - } - status = VerificationUtility.GetSignatureVerificationStatus(flags); + status = VerificationUtility.GetSignatureVerificationStatus(flags); - return new SignatureVerificationSummary(Type, status, flags, timestamp, expirationTime, issues); + return new SignatureVerificationSummary(Type, status, flags, timestamp, expirationTime, issues); + } } public string GetSigningCertificateFingerprint(HashAlgorithmName algorithm)
src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Timestamp.cs+77 −70 modified@@ -109,8 +109,6 @@ internal SignatureVerificationStatusFlags Verify( throw new ArgumentNullException(nameof(settings)); } - var flags = SignatureVerificationStatusFlags.NoErrors; - if (signature == null) { throw new ArgumentNullException(nameof(signature)); @@ -124,14 +122,16 @@ internal SignatureVerificationStatusFlags Verify( var timestamperCertificate = SignerInfo.Certificate; if (timestamperCertificate == null) { - flags |= SignatureVerificationStatusFlags.NoCertificate; - issues.Add(SignatureLog.Issue(treatIssueAsError, NuGetLogCode.NU3020, string.Format(CultureInfo.CurrentCulture, Strings.VerifyError_TimestampNoCertificate, signature.FriendlyName))); - return flags; + return SignatureVerificationStatusFlags.NoCertificate; } - flags |= VerificationUtility.ValidateTimestamp(this, signature, treatIssueAsError, issues, SigningSpecifications.V1); - if (flags == SignatureVerificationStatusFlags.NoErrors) + var timestampFlags = VerificationUtility.ValidateTimestamp(this, signature, treatIssueAsError, issues, SigningSpecifications.V1); + if (timestampFlags != SignatureVerificationStatusFlags.NoErrors) + { + return timestampFlags; + } + else { issues.Add(SignatureLog.InformationLog(string.Format(CultureInfo.CurrentCulture, Strings.TimestampValue, GeneralizedTime.LocalDateTime.ToString(CultureInfo.CurrentCulture)) + Environment.NewLine)); @@ -140,6 +140,7 @@ internal SignatureVerificationStatusFlags Verify( signature.FriendlyName, $"{Environment.NewLine}{CertificateUtility.X509Certificate2ToString(timestamperCertificate, fingerprintAlgorithm)}"))); + SignatureVerificationStatusFlags flags = SignatureVerificationStatusFlags.NoErrors; var certificateExtraStore = SignedCms.Certificates; using (X509ChainHolder chainHolder = X509ChainHolder.CreateForTimestamping()) @@ -170,94 +171,100 @@ internal SignatureVerificationStatusFlags Verify( if (chainBuildSucceed) { - return flags; + return SignatureVerificationStatusFlags.NoErrors; } + else if (chainStatusList.Length == 0) + { + return SignatureVerificationStatusFlags.UnknownBuildStatus; + } + else + { + var chainBuildingHasIssues = false; + IEnumerable<string> messages; - var chainBuildingHasIssues = false; - IEnumerable<string> messages; - - var timestampInvalidCertificateFlags = CertificateChainUtility.DefaultObservedStatusFlags; + var timestampInvalidCertificateFlags = CertificateChainUtility.DefaultObservedStatusFlags; - if (CertificateChainUtility.TryGetStatusAndMessage(chainStatusList, timestampInvalidCertificateFlags, out messages)) - { - foreach (var message in messages) + if (CertificateChainUtility.TryGetStatusAndMessage(chainStatusList, timestampInvalidCertificateFlags, out messages)) { - issues.Add(SignatureLog.Issue(treatIssueAsError, NuGetLogCode.NU3028, string.Format(CultureInfo.CurrentCulture, Strings.VerifyError_TimestampVerifyChainBuildingIssue, signature.FriendlyName, message))); - } + foreach (var message in messages) + { + issues.Add(SignatureLog.Issue(treatIssueAsError, NuGetLogCode.NU3028, string.Format(CultureInfo.CurrentCulture, Strings.VerifyError_TimestampVerifyChainBuildingIssue, signature.FriendlyName, message))); + } - flags |= SignatureVerificationStatusFlags.ChainBuildingFailure; - chainBuildingHasIssues = true; - } + flags |= SignatureVerificationStatusFlags.ChainBuildingFailure; + chainBuildingHasIssues = true; + } - // For all the special cases, chain status list only has unique elements for each chain status flag present - // therefore if we are checking for one specific chain status we can use the first of the returned list - // if we are combining checks for more than one, then we have to use the whole list. + // For all the special cases, chain status list only has unique elements for each chain status flag present + // therefore if we are checking for one specific chain status we can use the first of the returned list + // if we are combining checks for more than one, then we have to use the whole list. - if (CertificateChainUtility.TryGetStatusAndMessage(chainStatusList, X509ChainStatusFlags.UntrustedRoot, out messages)) - { - SignatureUtility.LogAdditionalContext(chain, issues); + if (CertificateChainUtility.TryGetStatusAndMessage(chainStatusList, X509ChainStatusFlags.UntrustedRoot, out messages)) + { + SignatureUtility.LogAdditionalContext(chain, issues); - issues.Add(SignatureLog.Error(NuGetLogCode.NU3028, string.Format(CultureInfo.CurrentCulture, Strings.VerifyTimestampChainBuildingIssue_UntrustedRoot, signature.FriendlyName))); + issues.Add(SignatureLog.Error(NuGetLogCode.NU3028, string.Format(CultureInfo.CurrentCulture, Strings.VerifyTimestampChainBuildingIssue_UntrustedRoot, signature.FriendlyName))); - flags |= SignatureVerificationStatusFlags.UntrustedRoot; - chainBuildingHasIssues = true; - } + flags |= SignatureVerificationStatusFlags.UntrustedRoot; + chainBuildingHasIssues = true; + } - if (CertificateChainUtility.TryGetStatusAndMessage(chainStatusList, X509ChainStatusFlags.Revoked, out messages)) - { - issues.Add(SignatureLog.Error(NuGetLogCode.NU3028, string.Format(CultureInfo.CurrentCulture, Strings.VerifyError_TimestampVerifyChainBuildingIssue, signature.FriendlyName, messages.First()))); - flags |= SignatureVerificationStatusFlags.CertificateRevoked; + if (CertificateChainUtility.TryGetStatusAndMessage(chainStatusList, X509ChainStatusFlags.Revoked, out messages)) + { + issues.Add(SignatureLog.Error(NuGetLogCode.NU3028, string.Format(CultureInfo.CurrentCulture, Strings.VerifyError_TimestampVerifyChainBuildingIssue, signature.FriendlyName, messages.First()))); + flags |= SignatureVerificationStatusFlags.CertificateRevoked; - return flags; - } + return flags; + } - var offlineRevocationErrors = CertificateChainUtility.TryGetStatusAndMessage(chainStatusList, X509ChainStatusFlags.OfflineRevocation, out var _); - var unknownRevocationErrors = CertificateChainUtility.TryGetStatusAndMessage(chainStatusList, X509ChainStatusFlags.RevocationStatusUnknown, out var unknownRevocationStatusMessages); - if (offlineRevocationErrors || unknownRevocationErrors) - { - if (treatIssueAsError) + var offlineRevocationErrors = CertificateChainUtility.TryGetStatusAndMessage(chainStatusList, X509ChainStatusFlags.OfflineRevocation, out var _); + var unknownRevocationErrors = CertificateChainUtility.TryGetStatusAndMessage(chainStatusList, X509ChainStatusFlags.RevocationStatusUnknown, out var unknownRevocationStatusMessages); + if (offlineRevocationErrors || unknownRevocationErrors) { - string unknownRevocationMessage = null; - - if (unknownRevocationErrors) + if (treatIssueAsError) { - unknownRevocationMessage = string.Format(CultureInfo.CurrentCulture, Strings.VerifyError_TimestampVerifyChainBuildingIssue, signature.FriendlyName, unknownRevocationStatusMessages.First()); - } + string unknownRevocationMessage = null; - if (settings.RevocationMode == RevocationMode.Offline) - { - if (offlineRevocationErrors) + if (unknownRevocationErrors) { - issues.Add(SignatureLog.InformationLog(string.Format(CultureInfo.CurrentCulture, Strings.VerifyError_TimestampVerifyChainBuildingIssue, signature.FriendlyName, Strings.VerifyCertTrustOfflineWhileRevocationModeOffline))); + unknownRevocationMessage = string.Format(CultureInfo.CurrentCulture, Strings.VerifyError_TimestampVerifyChainBuildingIssue, signature.FriendlyName, unknownRevocationStatusMessages.First()); } - if (unknownRevocationMessage != null) + if (settings.RevocationMode == RevocationMode.Offline) { - issues.Add(SignatureLog.InformationLog(unknownRevocationMessage)); + if (offlineRevocationErrors) + { + issues.Add(SignatureLog.InformationLog(string.Format(CultureInfo.CurrentCulture, Strings.VerifyError_TimestampVerifyChainBuildingIssue, signature.FriendlyName, Strings.VerifyCertTrustOfflineWhileRevocationModeOffline))); + } + + if (unknownRevocationMessage != null) + { + issues.Add(SignatureLog.InformationLog(unknownRevocationMessage)); + } } - } - else - { - if (offlineRevocationErrors) + else { - issues.Add(SignatureLog.Issue(!settings.AllowUnknownRevocation, NuGetLogCode.NU3028, string.Format(CultureInfo.CurrentCulture, Strings.VerifyError_TimestampVerifyChainBuildingIssue, signature.FriendlyName, Strings.VerifyCertTrustOfflineWhileRevocationModeOnline))); - } + if (offlineRevocationErrors) + { + issues.Add(SignatureLog.Issue(!settings.AllowUnknownRevocation, NuGetLogCode.NU3028, string.Format(CultureInfo.CurrentCulture, Strings.VerifyError_TimestampVerifyChainBuildingIssue, signature.FriendlyName, Strings.VerifyCertTrustOfflineWhileRevocationModeOnline))); + } + + if (unknownRevocationMessage != null) + { + issues.Add(SignatureLog.Issue(!settings.AllowUnknownRevocation, NuGetLogCode.NU3028, unknownRevocationMessage)); + } - if (unknownRevocationMessage != null) - { - issues.Add(SignatureLog.Issue(!settings.AllowUnknownRevocation, NuGetLogCode.NU3028, unknownRevocationMessage)); } + } + if (!chainBuildingHasIssues && (settings.AllowIgnoreTimestamp || settings.AllowUnknownRevocation)) + { + return SignatureVerificationStatusFlags.NoErrors; } - } - if (!chainBuildingHasIssues && (settings.AllowIgnoreTimestamp || settings.AllowUnknownRevocation)) - { - return flags; + flags |= SignatureVerificationStatusFlags.UnknownRevocation; + chainBuildingHasIssues = true; } - - flags |= SignatureVerificationStatusFlags.UnknownRevocation; - chainBuildingHasIssues = true; } // Debug log any errors @@ -269,9 +276,9 @@ internal SignatureVerificationStatusFlags Verify( Strings.VerifyError_InvalidCertificateChain, string.Join(", ", chainStatusList.Select(x => x.Status.ToString()))))); } - } - return flags; + return flags; + } } #endif }
src/NuGet.Core/NuGet.Packaging/Signing/Utility/CertificateChainUtility.cs+1 −1 modified@@ -94,7 +94,7 @@ public static IX509CertificateChain GetCertificateChain( } } - if (fatalStatuses.Any()) + if (chain.ChainStatus.Length == 0 || fatalStatuses.Count > 0) { if (certificateType == CertificateType.Timestamp) {
src/NuGet.Core/NuGet.Packaging/Signing/Utility/CertificateUtility.cs+6 −1 modified@@ -321,7 +321,12 @@ public static bool IsSelfIssued(X509Certificate2 certificate) X509VerificationFlags.IgnoreCertificateAuthorityRevocationUnknown | X509VerificationFlags.IgnoreEndRevocationUnknown; - CertificateChainUtility.BuildWithPolicy(chain, certificate); + bool buildSuccess = CertificateChainUtility.BuildWithPolicy(chain, certificate); + + if (!buildSuccess && chain.ChainStatus.Length == 0) + { + throw new SignatureException(Strings.CertificateChainValidationFailed); + } if (chain.ChainElements.Count != 1) {
src/NuGet.Core/NuGet.Packaging/Signing/Utility/SignatureUtility.cs+6 −1 modified@@ -661,7 +661,12 @@ private static IX509CertificateChain GetCertificateChain( chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; - CertificateChainUtility.BuildWithPolicy(chain, certificate); + bool buildSuccess = CertificateChainUtility.BuildWithPolicy(chain, certificate); + + if (!buildSuccess && chain.ChainStatus.Length == 0) + { + throw new SignatureException(Strings.CertificateChainValidationFailed); + } if (chain.ChainStatus.Any(chainStatus => chainStatus.Status.HasFlag(X509ChainStatusFlags.Cyclic) ||
src/NuGet.Core/NuGet.Packaging/Signing/Verification/SignatureVerificationStatusFlags.cs+7 −1 modified@@ -110,6 +110,11 @@ public enum SignatureVerificationStatusFlags /// </summary> MultipleTimestamps = 1 << 18, + /// <summary> + /// Unknown build status. + /// </summary> + UnknownBuildStatus = 1 << 19, + /// <summary> /// Flags which indicate that the signed package is suspect. /// </summary> @@ -137,6 +142,7 @@ public enum SignatureVerificationStatusFlags ChainBuildingFailure | UnknownRevocation | UntrustedRoot | - GeneralizedTimeOutsideValidity + GeneralizedTimeOutsideValidity | + UnknownBuildStatus } }
test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/SignatureVerificationStatusFlagsTests.cs+1 −0 modified@@ -42,6 +42,7 @@ public void EnumDefintion_HasNotChangedUnexpectedly() { "GeneralizedTimeOutsideValidity", 1 << 16 }, { "NoValidTimestamp", 1 << 17 }, { "MultipleTimestamps", 1 << 18 }, + { "UnknownBuildStatus", 1 << 19 }, { "Suspect", (int)(SignatureVerificationStatusFlags.IntegrityCheckFailed | SignatureVerificationStatusFlags.CertificateRevoked) }, { "Illegal", (int)(SignatureVerificationStatusFlags.NoCertificate |
test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/VerificationUtilityTests.cs+1 −0 modified@@ -33,6 +33,7 @@ public class VerificationUtilityTests [InlineData(SignatureVerificationStatusFlags.Suspect, SignatureVerificationStatus.Suspect)] [InlineData(SignatureVerificationStatusFlags.Illegal, SignatureVerificationStatus.Disallowed)] [InlineData(SignatureVerificationStatusFlags.Untrusted, SignatureVerificationStatus.Disallowed)] + [InlineData(SignatureVerificationStatusFlags.UnknownBuildStatus, SignatureVerificationStatus.Unknown)] public void GetSignatureVerificationStatus_WithStatusFlag_ReturnsStatus( SignatureVerificationStatusFlags flags, SignatureVerificationStatus expectedStatus)
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
7- github.com/advisories/GHSA-68w7-72jg-6qppghsaADVISORY
- msrc.microsoft.com/update-guide/vulnerability/CVE-2024-0057ghsavendor-advisoryWEB
- nvd.nist.gov/vuln/detail/CVE-2024-0057ghsaADVISORY
- github.com/NuGet/NuGet.Client/commit/3333f352ec47f0ebb489f20353dea7017f6cb00cghsaWEB
- github.com/NuGet/NuGet.Client/commit/5e1ba955cca14328d2cb5723f211d5fbc9bcacb3ghsaWEB
- github.com/NuGet/NuGet.Client/security/advisories/GHSA-68w7-72jg-6qppghsaWEB
- security.netapp.com/advisory/ntap-20240208-0007ghsaWEB
News mentions
0No linked articles in our index yet.