Summary
On Windows, CertGetCertificateChain is called with CERT_CHAIN_REVOCATION_CHECK_END_CERT, which triggers a network call to OCSP/CRL endpoints with a 10-second timeout. However, in verify_chain_policy, CERT_CHAIN_POLICY_IGNORE_ALL_REV_UNKNOWN_FLAGS is set, meaning revocation failures are silently ignored in the final policy decision.
This results in a blocking network call of up to 10 seconds that has no effect on whether the certificate is ultimately accepted or rejected.
Impact
In network-restricted environments (e.g., hosts with limited outbound access where OCSP/CRL endpoints are unreachable), the TLS handshake blocks for the full 10-second dwUrlRetrievalTimeout on every first connection attempt. This is particularly problematic f
or:
- Short-lived instances where the CRL cache is always cold
- Hosts behind firewalls that allow :443 to the application server but not to arbitrary OCSP responders
- Applications with request timeouts shorter than 10 seconds (the revocation timeout exceeds the application timeout, causing connection failures)
One can hit this e.g. after migrating from webpki-roots (no network calls) to rustls-platform-verifier (via reqwest 0.13).
Relevant code
In src/verification/windows.rs:
// Chain building — triggers network call
const FLAGS: u32 = CERT_CHAIN_REVOCATION_CHECK_END_CERT
| CERT_CHAIN_REVOCATION_ACCUMULATIVE_TIMEOUT
| CERT_CHAIN_CACHE_END_CERT;
parameters.dwUrlRetrievalTimeout = 10 * 1000; // 10 seconds
// Policy verification — ignores revocation failures
params.dwFlags = CERT_CHAIN_POLICY_IGNORE_ALL_REV_UNKNOWN_FLAGS;
Comparison with other implementations
- Go
crypto/x509 (root_windows.go): Calls CertGetCertificateChain without any CERT_CHAIN_REVOCATION_CHECK_* flags - no revocation network calls.
- The test configuration in this crate: Uses
CERT_CHAIN_CACHE_ONLY_URL_RETRIEVAL to prevent network calls, which confirms the production code intentionally makes them.
Suggestion
Would you consider one of the following?
-
Remove CERT_CHAIN_REVOCATION_CHECK_END_CERT from the flags, since the result is discarded by the policy step anyway. This eliminates the network call with no change in security posture.
-
Make revocation checking configurable via a builder option on Verifier (e.g., with_revocation_check(bool) or with_revocation_check(RevocationPolicy)) so consumers can opt out in environments where the network call is problematic.
-
Use CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY by default (check cached CRLs without making network calls), with an opt-in for full network-based revocation.
Environment
- Windows Server 2025
- rustls-platform-verifier 0.7.x
- reqwest 0.13
Summary
On Windows,
CertGetCertificateChainis called withCERT_CHAIN_REVOCATION_CHECK_END_CERT, which triggers a network call to OCSP/CRL endpoints with a 10-second timeout. However, inverify_chain_policy,CERT_CHAIN_POLICY_IGNORE_ALL_REV_UNKNOWN_FLAGSis set, meaning revocation failures are silently ignored in the final policy decision.This results in a blocking network call of up to 10 seconds that has no effect on whether the certificate is ultimately accepted or rejected.
Impact
In network-restricted environments (e.g., hosts with limited outbound access where OCSP/CRL endpoints are unreachable), the TLS handshake blocks for the full 10-second
dwUrlRetrievalTimeouton every first connection attempt. This is particularly problematic for:
One can hit this e.g. after migrating from
webpki-roots(no network calls) torustls-platform-verifier(via reqwest 0.13).Relevant code
In
src/verification/windows.rs:Comparison with other implementations
crypto/x509(root_windows.go): CallsCertGetCertificateChainwithout anyCERT_CHAIN_REVOCATION_CHECK_*flags - no revocation network calls.CERT_CHAIN_CACHE_ONLY_URL_RETRIEVALto prevent network calls, which confirms the production code intentionally makes them.Suggestion
Would you consider one of the following?
Remove
CERT_CHAIN_REVOCATION_CHECK_END_CERTfrom the flags, since the result is discarded by the policy step anyway. This eliminates the network call with no change in security posture.Make revocation checking configurable via a builder option on
Verifier(e.g.,with_revocation_check(bool)orwith_revocation_check(RevocationPolicy)) so consumers can opt out in environments where the network call is problematic.Use
CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLYby default (check cached CRLs without making network calls), with an opt-in for full network-based revocation.Environment