Certificate Path Building and Validation

X.509 certificate verification splits into two distinct problems that are easy to conflate: building a candidate certification path from a target (leaf) certificate back to a trust anchor, and validating that path once built. RFC 4158 covers building; RFC 5280 §6 covers validation. They are separate because the method used to assemble the chain does not change whether the chain is valid — but a chain that was never built can never be validated, so building is every bit as security-relevant as validation. Most real-world “certificate error” mysteries (works in Chrome, fails in curl; works in curl, fails in Node) are path-building divergences, not validation failures.12

The trust model

A relying party is initialized with a small set of trust anchors (public key + subject DN it already trusts, usually self-signed root CA certificates in a local trust store). A certification path is an ordered sequence of certificates beginning with a certificate verifiable by a trust anchor and ending with the target certificate, each certificate signed by the one before it. RFC 5280 §3.2 frames this as the core PKIX problem: the public-key user starts with only a limited number of assured CA keys, so paths have to be found through intermediate CAs the user does not directly trust. Trust anchors need not be roots — any certificate in the trust store can terminate a path, which is what “partial chain” semantics exploit (below).3

Path building (RFC 4158)

Path building is the assembly step: starting from the target certificate (forward direction) or from a trust anchor (reverse direction), find issuer certificates until the path connects. Building is deliberately not standardized — RFC 4158 provides guidance and criteria rather than one blessed algorithm, because PKI structures vary (hierarchies, meshes, cross-certified, bridge). Its two headline criteria: the implementation should be able to find all possible paths (not just the first), and it should be efficient — prefer paths more likely to validate under RFC 5280 before unlikely ones, with loop detection and bounded backtracking. Intermediates may be sourced from anywhere: the TLS handshake itself, a local cache/store, LDAP, HTTP, or an Authority Information Access (AIA) caIssuers URI embedded in the certificate. This freedom of sourcing is exactly where implementations diverge.4

Path validation (RFC 5280 §6)

Validation is the standardized part: given a prospective path of length n, run the §6.1 algorithm — check well-formedness, signatures, validity periods, name constraints, policy processing, basic constraints, and key usage — and return success/failure plus outputs. Conforming implementations are not required to implement this exact algorithm but must provide equivalent functionality. Critically, validation operates on a path already in hand: §6.1.1’s first input is “a prospective certification path of length n.” If the builder never assembled a complete path, validation has nothing to run on and the connection fails with an “unable to get local issuer certificate”-class error — a building failure surfacing as a validation error.5

Where implementations diverge — the “works here, fails there” pattern

Because building is unstandardized, clients make different sourcing choices, and the same server can look valid to one client and broken to another:

  • Chrome/Firefox cache intermediates they’ve seen before and can fetch missing ones via AIA, so a server that sends only a leaf often still verifies in the browser.
  • curl/OpenSSL by default requires an uninterrupted chain from the target to a root in the trust store — but OpenSSL’s chain builder stops at the first self-signed certificate it adds, and its -partial_chain flag (X509_V_FLAG_PARTIAL_CHAIN) relaxes termination to “any certificate in the trust store,” including an intermediate. A VPN/TLS-interception middlebox whose root is absent from the store can therefore still verify under partial-chain semantics if the store happens to contain one of the chain’s intermediates — which is why a connection can succeed with only an intermediate CA cert locally present.6
  • Node.js (and much OpenSSL-based tooling with default flags) validates the full chain to a trust anchor without partial-chain leniency, so the same middlebox fails hard until the actual root CA is added to the store.

This is the textbook explanation for TLS-interception pain: the diagnostic that “works” (Chrome, curl with partial chain) proves only that some path exists, not that the path terminates where the failing client requires. The fix is always the same — get the true trust anchor into the client’s store — but identifying why one client accepted an intermediate-only chain requires understanding that building and trust-anchor termination are implementation choices, not RFC 5280 mandates.

OpenSSL’s concrete procedure

OpenSSL’s verification options doc spells out the mechanics: chain building proceeds iteratively from the target, matching candidate issuers by subject-name == issuer-name plus (when present) authority-key-identifier fields; the trust store is searched first, then the untrusted/intermediate list — and once any issuer is found in the trust store, untrusted sources are no longer consulted. Construction stops at the first self-signed certificate, which must then fully match a trust anchor or building fails (unless -partial_chain is set). Only after a chain is built does validation check extensions, purpose (e.g. sslserver), trust settings on the last certificate, validity dates, and signatures. The ordering — build first, validate second, trust store consulted before intermediates — is what produces the surprising behaviors above.7

Sources

Footnotes

  1. M. Cooper, Y. Dzambasow, P. Hesse, S. Joseph, R. Nicholas 2005 — RFC 4158: Internet X.509 PKI Certification Path Building (Sections 1 and 2 excerpts) ↩

  2. D. Cooper, S. Santesson, S. Farrell, S. Boeyen, R. Housley, W. Polk 2008 — RFC 5280: Internet X.509 PKI Certificate and CRL Profile (Sections 3.2 and 6.1 excerpts) ↩

  3. D. Cooper, S. Santesson, S. Farrell, S. Boeyen, R. Housley, W. Polk 2008 — RFC 5280: Internet X.509 PKI Certificate and CRL Profile (Sections 3.2 and 6.1 excerpts) ↩

  4. M. Cooper, Y. Dzambasow, P. Hesse, S. Joseph, R. Nicholas 2005 — RFC 4158: Internet X.509 PKI Certification Path Building (Sections 1 and 2 excerpts) ↩

  5. D. Cooper, S. Santesson, S. Farrell, S. Boeyen, R. Housley, W. Polk 2008 — RFC 5280: Internet X.509 PKI Certificate and CRL Profile (Sections 3.2 and 6.1 excerpts) ↩

  6. 2026 — openssl-verification-options - generic X.509 certificate verification options ↩

  7. 2026 — openssl-verification-options - generic X.509 certificate verification options ↩