Uh oh!
There was an error while loading. Please reload this page.
Normalize X509Chain App/Cert policies across OSes - #132348
Conversation
The original policy handling code was written before contextual trust, which made it hard to write good tests. Now that we have more tests, unify the behaviors as best we can, even across invalidly encoded extensions.
|
Azure Pipelines: Successfully started running 3 pipeline(s). 13 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
bartonjs
commented
Aug 14, 2026
/azp run runtime-libraries-coreclr outerloop |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
bartonjs
commented
Aug 14, 2026
/azp run runtime-extra-platforms |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
Pull request overview
This PR updates X509Chain policy processing so ApplicationPolicy/CertificatePolicy handling (and invalid/undecodable policy-related extensions) is evaluated and reported more consistently across Windows/OpenSSL/Apple/Android, and adjusts/expands tests to match the unified behavior.
Changes:
- Refactors
CertificatePolicyChainto compute per-chain-element “encoding” vs “usage” errors and exposes helpers to reuse the same logic across platform chain processors. - Updates OpenSSL, Apple, and Android chain processors to merge policy/encoding errors into chain + element status consistently (and to detect encoding issues even when no explicit policy filtering is requested).
- Normalizes existing tests’ OS-conditional expectations and adds focused test suites for app-policy vs EKU behavior and corrupt policy-related extensions.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| src/libraries/System.Security.Cryptography/tests/X509Certificates/RevocationTests/DynamicRevocationTests.cs | Removes OS-conditional expectations for NotValidForUsage at non-leaf levels. |
| src/libraries/System.Security.Cryptography/tests/X509Certificates/DynamicChainTests.cs | Refactors/makes helpers reusable by new tests; factors out shared DER encoding for policy extensions. |
| src/libraries/System.Security.Cryptography/tests/X509Certificates/CorruptPoliciesChainTests.cs | New coverage for corrupt/undecodable policy/EKU-related extensions and expected chain-element status behavior. |
| src/libraries/System.Security.Cryptography/tests/X509Certificates/ChainTests.cs | Normalizes expectations around NotValidForUsage across platforms. |
| src/libraries/System.Security.Cryptography/tests/X509Certificates/AppAndCertPoliciesChainTests.cs | New tests covering certificate policy constraints/mappings plus Application Policies vs EKU interactions. |
| src/libraries/System.Security.Cryptography/tests/System.Security.Cryptography.Tests.csproj | Adds the new test files to the test project. |
| src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509ChainProcessor.cs | Splits policy evaluation into “merge errors” and “process policy”; adds encoding-only validation when no policy filters are requested. |
| src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.Apple.cs | Switches to shared policy-chain logic and per-element error attribution. |
| src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.Android.cs | Switches to shared policy-chain logic and per-element error attribution. |
| src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePolicy.cs | Implements CertificatePolicyChain.Build/CheckEncodingOnly, per-element error vectors, and revised EKU/app-policy semantics. |
| src/libraries/Common/src/System/Security/Cryptography/Oids.cs | Adds AnyEnhancedKeyUsage constant used in policy evaluation. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.
Suppressed comments (2)
src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePolicy.cs:661
ErrorVector's scalar bit test uses(1 << index)(anintshift). For indices >= 31 this overflows/sign-extends and will report the wrong bit, so long chains can misattribute policy/encoding errors to the wrong element.
internal bool this[int index]
{
get
{
if (_vector is null)
{
return (_scalar & (1 << index)) != 0;
}
src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePolicy.cs:456
- The comment about only checking EKU “for structural validity” when ApplicationCertPolicies is present but corrupt is misleading: this block currently skips EKU entirely whenever ApplicationCertPolicies is present (even if it failed to decode). Either update the comment to match the behavior, or add the intended validation call.
if (policyData.EnhancedKeyUsage != null)
{
// If policyData.ApplicationCertPolicies is present, but corrupt, applicationCertPolicies
// should stay null, we'll only check EKU for structural validity.
if (policyData.ApplicationCertPolicies is null)
{
applicationCertPolicies = ReadExtendedKeyUsageExtension(policyData.EnhancedKeyUsage);
}
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.
Suppressed comments (3)
src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePolicy.cs:456
ReadExtendedKeyUsageExtensioncan throwCryptographicExceptionon malformed EKU. In this code path (policy filtering active and no ApplicationCertPolicies extension), the exception is not caught, which would cause chain building to throw instead of reportingInvalidExtension/InvalidPolicyConstraintsviaencodingErrors.
// should stay null.
if (policyData.ApplicationCertPolicies is null)
{
applicationCertPolicies = ReadExtendedKeyUsageExtension(policyData.EnhancedKeyUsage);
}
src/libraries/System.Security.Cryptography/tests/X509Certificates/DynamicChainTests.cs:18
- The
RSATestDatausing-alias appears to be unused, which can trigger CS8019/IDE0005 in builds that enforce unused usings.
using RSATestData = System.Security.Cryptography.Rsa.Tests.TestData;
src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.Android.cs:424
InvalidPolicyConstraintsis being reported withSR.Chain_NoPolicyMatch, which describes a policy mismatch rather than a malformed/invalid extension. This can makeX509ChainStatus.StatusInformationmisleading for encoding failures.
Status = X509ChainStatusFlags.InvalidPolicyConstraints,
// "NoPolicyMatch" says that the policy is "invalid", which works for this one, too.
StatusInformation = SR.Chain_NoPolicyMatch,
The "AppPol=NULL(05 00) critical EKU=Server; req=Server" test case is the only one that set the critical bit, and it failed with PartialChain on Android. Logic dictates that it failed because Android doesn't support that extension, and it's marked as critical. Rather than giving it a platform-dependent expected value, just delete the case.
bartonjs
commented
Aug 26, 2026
/azp run runtime-extra-platforms |
|
Azure Pipelines will not run the associated pipelines, because the pull request was updated after the run command was issued. Review the pull request again and issue a new run command. |
bartonjs
commented
Aug 26, 2026
/azp run runtime-extra-platforms |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.
Suppressed comments (2)
Previously missed (2) — in code that hasn't changed since the last review.
src/libraries/System.Security.Cryptography/tests/X509Certificates/DynamicChainTests.cs:1147
- Use UtcNow instead of Now for certificate validity timestamps to avoid time zone/DST sensitivity in CI and local runs.
DateTimeOffset notBefore = DateTimeOffset.Now.AddMinutes(-5);
src/libraries/System.Security.Cryptography/tests/X509Certificates/AppAndCertPoliciesChainTests.cs:235
- Remove trailing whitespace in this initializer (it can cause noisy diffs and violates common formatting expectations).
X509BasicConstraintsExtension.CreateForCertificateAuthority(), bartonjs
commented
Aug 27, 2026
I've trawled the logs, and I attest, to the best of my ability, that none of the extra-platforms test failures are caused by this change. (And I'm astounded at how many of them report failure when all tests passed and the runner script reports that it's returning success) |
bartonjs
commented
Aug 28, 2026
/ba-g Many DeadLetters, other failures were investigated. |
Uh oh!
There was an error while loading. Please reload this page.
bartonjs
commented
Aug 28, 2026
/backport-to release/11.0 |
bartonjs
commented
Aug 28, 2026
/backport to release/11.0 |
Started backporting to |
…2904) Backport of #132348 to release/11.0 /cc @bartonjs ## Customer Impact - [X] Customer reported - [X] Found internally Users of the X509Chain API could encounter platform-specific differences regarding handling of the ChainPolicy.ApplicationPolicies and ChainPolicy.CertificatePolicies validators and their interaction with the ms-appPolicy, EKU, CertPolicy, and CertPolicyMapping extensions, leading to the chain to report a certificate suitable for usage on some systems while unsuitable for usage on others (both false-positives and false-negatives). Some certificates gave a solid true/false on Windows, but caused exceptions on other platforms. ## Regression - [ ] Yes - [X] No The managed certificate policy validator (which is trying to emulate Windows for .NET Framework compatibility) hasn't substantially changed since 2015. ## Testing > How was the fix verified? A whole lot of new tests are added in this change. > How was the issue missed previously? The component was written before the CertificateRequest API was created, and at the time creating test certificates was a laborious process and involved checking in test cases. > What tests were added? Many tests were added involving corrupt extensions, certificate policy mappings, any-policy and inhibit-any-policy, et cetera. These new tests are believed to be comprehensive for the area. ## Risk Low, due to the added test coverage. Co-authored-by: Jeremy Barton <jbarton@microsoft.com>
The original policy handling code was written before contextual trust, which made it hard to write good tests. Now that we have more tests, unify the behaviors as best we can, even across invalidly encoded extensions.
Fixes#31246 (and maybe others)