pkix-lint
Advisory lint engine for X.509 certificate chains — CA/B Forum and RFC rules with structured soft-fail results, deviations, and exportable evidence packs.
What this crate provides
pkix-path::validate_path returns Result<ValidatedPath, Error> — hard pass
or fail. That binary model cannot express "this certificate is RFC 5280 valid
but violates CA/B Forum TLS BR §7.1.4.2" without aborting validation entirely.
pkix-lint adds an advisory layer on top:
Linttrait — the unit of evaluation. Each lint has a stable ID, a normative citation, a severity (Warn,Error,Fatal), a scope (CertificateorPath), and a subject-kind filter (Leaf,IntermediateCa,AnchorIssued, orAny).LintResult—Pass | NotApplicable | Warn | Error | Fatal.WarnandErrorcarry a static detail message.Fatalstops further lint evaluation for that item; it does not propagate as a hard failure.Finding— a lint ID paired with a result and the chain index of the offending certificate.LintRunner— evaluates a set ofdyn Lintobjects against a certificate or validated path, returningVec<Finding>.LintProfiletrait — extendspkix_path::Profilewith alints()method so a profile struct bundles its own lint set.deviationmodule — a waiver/exception mechanism that records approved deviations from lint rules for audit purposes.EvaluationReport— an exportable evidence pack suitable for OSCAL Assessment Results and compliance audits.
Advisory-only contract
pkix-lint findings never cause a certificate to be rejected. All runner
methods return Vec<Finding> — never Result::Err. Whether to act on a
finding is the caller's decision, configured per finding ID at the integration
layer. This is intentional:
- Spec ambiguity (CA/B Forum CPs, FPKI CPs) means some findings require human judgment before enforcement.
pkix-lintdoes not know whether you are in audit, monitoring, or hard-fail enforcement context. The caller does.
Built-in lints (pkix-lint::cabf_tls_br)
| ID | Rule | Scope |
|---|---|---|
cabf.br.tls.validity.max |
SC-081 phased validity cap (47–398 days) | Leaf |
cabf.br.tls.alg.sha1_prohibited |
SHA-1 signature algorithm prohibited | All |
cabf.br.tls.rsa.min_key_size |
RSA modulus ≥ 2048 bits | Leaf |
cabf.br.tls.san.required |
SubjectAltName extension required and non-empty | Leaf |
cabf.br.tls.eku.server_auth |
id-kp-serverAuth EKU required |
Leaf |
cabf.br.tls.bc.ca_flag |
cA = TRUE required on non-leaf certs |
Intermediate |
Use CabfTlsBrProfile (implements LintProfile) to run all built-in TLS BR
lints with a single call to run_chain.
Usage
Run built-in CA/B Forum TLS BR lints against a chain
use ;
use SubjectKind;
let profile = CabfTlsBrProfile;
let runner = profile.lint_runner;
let kinds = vec!;
let findings = runner.run_chain;
for f in findings.iter.filter
Implement a custom lint
use ;
use Certificate;
;
let runner = new;
Record a deviation (waiver)
use ;
let mut store = new;
store.add?;
Export an evidence pack
use EvaluationReport;
let mut report = new;
report.record_findings;
let json = to_string_pretty?; // requires `serde` feature
Finding ID stability
Finding IDs returned by Lint::id() are part of the public API and must not
change between crate versions without a semver-major bump. Format convention:
<regime>.<section>.<noun>, e.g. "cabf.br.tls.validity.max".
Features
| Feature | Enables |
|---|---|
serde |
Serialize/Deserialize on Finding, EvaluationReport, Deviation, and related types |
Standards
- CA/B Forum Baseline Requirements for TLS Server Certificates (SC-081)
- CA/B Forum S/MIME Baseline Requirements
- [RFC 5280] — Internet X.509 PKI Certificate and CRL Profile
License
Apache-2.0 OR MIT