Validate certificate path (RFC 5280 §6.1 on an ordered path, link signatures)
validate_certificate_pathValidates a leaf-first X.509 certificate path against specified trust anchors. Checks link signatures, validity, constraints, and policy to produce a trust verdict.
Instructions
RFC 5280 §6.1 validation of a path YOU ordered (path, leaf first, then each issuer) against YOUR trustAnchors at at: validity, basic constraints, key usage, name constraints and the policy inputs. By default every link signature is verified first — certificate i against i+1, the last against the anchor whose subject matches its issuer — and reported per link in signatures[] (PKI_REASON_SIGNATURE_INVALID fails the verdict). checkSignatures:false gives a structural verdict: valid stays false (PKI_REASON_SIGNATURE_NOT_CHECKED on every link) and failingReasons carries what actually fails; signaturesChecked says which one you got. No revocation here (verify_certificate_chain judges CRL / OCSP evidence; check_crl_revocation / check_ocsp_status judge one certificate). A negative verdict is valid:false + reasons[], never isError. Pin at for a reproducible, cacheable verdict. SHA-1 signatures need allowSha1:true. Token-frugal: verbosity:'summary'.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| at | No | The instant the verdict is evaluated at. An ISO 8601 date-time (UTC unless zoned; e.g. 2027-01-01T00:00:00Z), epoch milliseconds as digits, or 'now'. Omitted: PKINATIVE_MCP_AT when the operator pinned it, else the wall clock (a clock-dependent result is never cached). | |
| path | Yes | The path to validate, leaf FIRST, then each issuer up to (but not necessarily including) the anchor (every PEM block of every item is taken). Every PEM block of every item is taken, in order. | |
| fields | No | Dot-paths to keep after verbosity (arrays map over elements); unmatched paths land in _meta.unmatchedFields. | |
| limits | No | Raise pkinative's 22 named security bounds for this call (trusted input only; absent keys keep the engine defaults). A value above an operator ceiling (PKINATIVE_MCP_MAX_INPUT_BYTES, PKINATIVE_MCP_MAX_KDF_ITERATIONS, PKINATIVE_MCP_MAX_PATHS_EXPLORED) is LIMIT_CEILING_EXCEEDED; describe_engine lists the defaults and the ceilings. | |
| policy | No | RFC 5280 §6.1.1 policy inputs. | |
| strict | No | Escalate the first engine warning to a PKI_STRICT_DIAGNOSTIC error instead of listing it in diagnostics[]. | |
| pemMode | No | 'strict' (RFC 7468 exactly, default) or 'lax' (tolerates whitespace, line length and RFC 1421 headers). | strict |
| allowSha1 | No | Accept or produce SHA-1 signatures (legacy material you already trust). Default false: refused with PKI_CRYPTO_ALGORITHM_REFUSED on read, VALIDATION_ERROR on write. | |
| verbosity | No | 'summary' keeps the scalar fields only (token-frugal). | full |
| trustAnchors | Yes | Trust anchors (root certificates you trust) (every PEM block of every item is taken). At least one is required: a verdict is relative to the anchors you name. | |
| encodingRules | No | 'der' (strict X.690 DER, default) or 'ber' (indefinite / non-minimal lengths and constructed strings, as legacy CMS producers write). | der |
| checkSignatures | No | Verify every link signature before validating (certificate i against i+1, the last against the anchor whose subject is its issuer). false = structural verdict only: PKI_REASON_SIGNATURE_NOT_CHECKED stays in reasons[], signaturesChecked:false. |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| path | No | The path as validated, leaf first, up to (and including) the trust anchor it reached. | |
| valid | No | The engine verdict. With checkSignatures:false it is always false (every link is PKI_REASON_SIGNATURE_NOT_CHECKED): read failingReasons for the structural verdict. | |
| reasons | No | Why the verdict is negative (empty when valid): the engine PKI_REASON_* codes, each with the standard it cites and the path of the offending element. A reason is returned, never thrown. | |
| pathLength | No | ||
| signatures | No | One row per certificate of the input path: the issuer it was verified against (the next certificate, or the matching anchor) and the verdict; not-checked when no issuer was found or checkSignatures is false. | |
| diagnostics | No | Non-fatal concerns the engine raised (PKI_DIAG_*, de-duplicated, at most 200; explain_code explains one). | |
| evaluatedAt | No | The ISO instant used — re-pass it as `at` to reproduce the verdict. | |
| reasonCodes | No | ||
| failingReasons | No | The reasons that fail THIS call: reasons[] as is when the signatures were checked, minus the PKI_REASON_SIGNATURE_NOT_CHECKED markers otherwise. Empty = the path validates (structurally, when signaturesChecked is false). | |
| diagnosticCount | No | ||
| diagnosticCounts | No | Occurrences per diagnostic code. | |
| evaluatedAtSource | No | ||
| signatureVerdicts | No | ||
| signaturesChecked | No | ||
| failingReasonCodes | No | ||
| diagnosticsTruncated | No | true when distinct diagnostics beyond the 200 listed were dropped. |