VYPR
Critical severityNVD Advisory· Published Jan 9, 2024· Updated Jun 3, 2025

NET, .NET Framework, and Visual Studio Security Feature Bypass Vulnerability

CVE-2024-0057

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.

PackageAffected versionsPatched versions
NuGet.CommandLineNuGet
>= 4.6.0, < 5.11.65.11.6
NuGet.PackagingNuGet
>= 4.6.0, < 5.11.65.11.6
NuGet.CommandLineNuGet
>= 6.0.0, < 6.0.66.0.6
NuGet.PackagingNuGet
>= 6.0.0, < 6.0.66.0.6
NuGet.CommandLineNuGet
>= 6.3.0, < 6.3.46.3.4
NuGet.PackagingNuGet
>= 6.3.0, < 6.3.46.3.4
NuGet.CommandLineNuGet
>= 6.4.0, < 6.4.36.4.3
NuGet.PackagingNuGet
>= 6.4.0, < 6.4.36.4.3
NuGet.CommandLineNuGet
>= 6.6.0, < 6.6.26.6.2
NuGet.PackagingNuGet
>= 6.6.0, < 6.6.26.6.2
NuGet.CommandLineNuGet
>= 6.7.0, < 6.7.16.7.1
NuGet.PackagingNuGet
>= 6.7.0, < 6.7.16.7.1
NuGet.CommandLineNuGet
>= 6.8.0, < 6.8.16.8.1
NuGet.PackagingNuGet
>= 6.8.0, < 6.8.16.8.1

Affected products

93

Patches

2
5e1ba955cca1

Merged PR 502035: Handle no error status in chain

https://github.com/NuGet/NuGet.ClientMartin RuizJan 4, 2024via ghsa
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)
    
3333f352ec47

Merged PR 502035: Handle no error status in chain

https://github.com/NuGet/NuGet.ClientMartin RuizJan 4, 2024via ghsa
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

News mentions

0

No linked articles in our index yet.