GHSA-pwjx-qhcg-rvj4
ADVISORY - githubSummary
There is a certificate revocation enforcement bug in rustls-webpki CRL processing. when both the certificate CRL distribution point and the CRL issuing distribution point contain multiple URI names, IssuingDistributionPoint::authoritative_for() reuses one-shot DER iterators across nested comparisons. If the only matching URI pair appears later in both sequences, the implementation misses the match, treats the CRL as non-authoritative, and under UnknownStatusPolicy::Allow accepts a revoked certificate.
affected versions
revocation support shipped in 0.104.0-alpha.4, and the same iterator-reuse logic is still present at commit e4590782afc1207c3e46ba1249e7c3fb9da95198 on 2026-03-20. i did not identify an upstream fix as of that date.
affected component
- component: CRL authority matching for certificate DP vs CRL IDP names
- repo pin:
https://github.com/rustls/webpki@e4590782afc1207c3e46ba1249e7c3fb9da95198 - callsite:
src/crl/types.rs:626,src/crl/types.rs:649,src/crl/types.rs:664 - pinned source: https://github.com/rustls/webpki/blob/e4590782afc1207c3e46ba1249e7c3fb9da95198/src/crl/types.rs#L626-L678
technical details
RFC 5280 section 5.2.5 and section 6.3.3(b)(2)(i) require the verifier to check whether one of the names in the IDP matches one of the names in the certificate DP. the current implementation contradicts that requirement in the later-match case because iterator state, not the actual set of URI names, determines whether later names are considered.
the attached PoC uses a single trust anchor and a single relevant CRL path. there is no alternate unconstrained root or duplicate trust path for the same key material, so the acceptance result is attributable to the DP/IDP matching bug rather than chain-builder fallback.
the vulnerable flow is:
authoritative_for()parsesidp_general_namesonce before iterating certificate distribution points.- each certificate DP fullName is parsed into another one-shot
DerIterator. uri_name_in_common()iterates the first IDP URI and drains the DP iterator while looking for a match.- if the matching URI pair is second in both lists, it is never compared.
- the CRL is treated as non-authoritative, and
UnknownStatusPolicy::Allowconverts that into a successful verification result for a revoked certificate.
the repository already has a single-URI happy-path revocation test, which demonstrates the expected rejection path when the first URI matches. the attached PoC shows that simply moving the valid match to second position flips the result from Err(CertRevoked) to Ok(()) under the permissive status policy.
steps to reproduce
the attached poc.zip contains a cargo-based integration harness. after extracting it, run make canonical to produce the vulnerable result and make control for the negative controls.
unzip poc.zip -d poc
cd poc
make canonical
make control
the canonical run emits:
[CALLSITE_HIT]: authoritative_for::uri_name_in_common later_uri_pair_skipped=true
[PROOF_MARKER]: vuln_case=Ok(()) first_uri_control=Err(CertRevoked) later_match_position=second allow_unknown=true
[IMPACT_MARKER]: revoked_cert_accepted=true policy=UnknownStatusPolicy::Allow
the control run emits:
[CALLSITE_HIT]: authoritative_for::uri_name_in_common control_path=true
[NC_MARKER]: first_uri_control=Err(CertRevoked) deny_policy=Err(UnknownRevocationStatus) vuln_blocked=true
recommended fix
avoid reusing exhausted DER iterators across nested DP/IDP comparisons. a minimal fix is to reparse or snapshot the URI name sets for each comparison so that every IDP URI can be compared against the full DP URI set. a regression test should cover the case where the only valid URI match is later in both sequences.
cheers, Oleh Konko
Common Weakness Enumeration (CWE)
Improper Check for Certificate Revocation
GitHub
0.7
CVSS SCORE
4.4medium| Package | Type | OS Name | OS Version | Affected Ranges | Fix Versions |
|---|---|---|---|---|---|
| rustls-webpki | cargo | - | - | >=0.101.0,<0.103.10 | 0.103.10 |
| rustls-webpki | cargo | - | - | >=0.104.0-alpha.1,<0.104.0-alpha.5 | 0.104.0-alpha.5 |
CVSS:3 Severity and metrics
The CVSS metrics represent different qualitative aspects of a vulnerability that impact the overall score, as defined by the CVSS Specification.
The vulnerable component is bound to the network stack, but the attack is limited at the protocol level to a logically adjacent topology. This can mean an attack must be launched from the same shared physical (e.g., Bluetooth or IEEE 802.11) or logical (e.g., local IP subnet) network, or from within a secure or otherwise limited administrative domain (e.g., MPLS, secure VPN to an administrative network zone). One example of an Adjacent attack would be an ARP (IPv4) or neighbor discovery (IPv6) flood leading to a denial of service on the local LAN segment (e.g., CVE-2013-6014).
A successful attack depends on conditions beyond the attacker's control, requiring investing a measurable amount of effort in research, preparation, or execution against the vulnerable component before a successful attack.
The attacker requires privileges that provide significant (e.g., administrative) control over the vulnerable component allowing access to component-wide settings and files.
The vulnerable system can be exploited without interaction from any user.
An exploited vulnerability can only affect resources managed by the same security authority. In this case, the vulnerable component and the impacted component are either the same, or both are managed by the same security authority.
There is no loss of confidentiality.
There is a total loss of integrity, or a complete loss of protection. For example, the attacker is able to modify any or all files protected by the impacted component. Alternatively, only some files can be modified, but malicious modification would present a direct, serious consequence to the impacted component.
There is no impact to availability within the impacted component.
RustSec
-