Fixes
Certificate Transparency & PKI Health · Updated 2026-05-02
TLS Chain Trust
Worst-host TLS chain trust (15 pts). Untrusted or incomplete chain on any sampled host fails the whole check.
TLS Chain Trust verifies that the certificate chain served by each sampled HTTPS host validates end-to-end against the system trust store, with hostname verification on. The score is driven by the WORST host: any sampled host that fails strict verification fails the whole 15-point check. The signal is the same as the Chain Completeness web sub-weight, but the scope is broader (CT-category sample) and the aggregation is MIN, not weighted average.
If you got a low score here, the actual fix is in the Chain Completeness guide (Web Application Security): serve the full intermediate chain, ensure SAN coverage, and use a current CA root. This page focuses on what is unique about CT-category aggregation.
How the check works
Per scan, RedScore samples HTTPS hosts and runs a strict TLS handshake against each (Python ssl with default trust store + hostname verification). Per-host bands:
- Trusted chain validates: 1.0 (band: trusted_chain).
- Verify error matches "self signed", "unable to get local issuer certificate", "certificate verify failed", or "unknown ca": 0.0 (band: untrusted_or_incomplete). Reason: ct_chain_untrusted_or_incomplete.
- TLS handshake itself failed: 0.0 (band: tls_unavailable). Reason: ct_chain_untrusted_or_incomplete.
- Other verification error (ordering, partial validation): 0.5 (band: ordering_or_validation_issue). Reason: ct_chain_ordering_or_validation_issue.
Composite = MIN of all host scores. Verdict via the standard CT composite mapping.
How the verdict maps to evidence
- Pass: every sampled host's chain validates strictly.
- Warn: at least one host returns a non-terminal validation issue (ordering, partial chain).
- Fail: at least one host's chain is untrusted, incomplete, or fails handshake entirely.
Evidence shows chain_validation_rows with each host's tls_handshake_ok flag, trusted_chain_ok flag, the verify_error string, the assigned band, and the per-host score.
Special states
- Unavailable: no HTTPS samples could be obtained. Fix Web Assessability or HTTPS Consistency first.
Fix: read the verify_error per failing host
The verify_error field tells you exactly why each host failed. Map the error to the right fix:
Self-signed or unknown CA
Cert is signed by a CA the public trust store does not recognize. Common causes: a self-signed cert generated for testing was left on a production host; an internal CA cert not added to public trust stores; a cert from a CA whose root expired (DST Root CA X3 in 2021, for example). Fix: re-issue from a publicly-trusted CA. Let's Encrypt is free and trusted everywhere.
Unable to get local issuer certificate / unable to verify the first certificate
The leaf cert is fine but the server is not sending the intermediate(s). The most common cause is pointing your web server at cert.pem instead of fullchain.pem. See the Chain Completeness fix for per-server config (nginx, Apache, Caddy, IIS, CDN).
Certificate verify failed (other)
Catch-all for other validation issues: hostname mismatch, expired cert, signature algorithm rejected. Run openssl s_client -connect host:443 -servername host -verify_return_error < /dev/null and read the explicit error.
Ordering or validation issue (warn-tier)
Chain validates eventually but had a non-terminal issue. Often: intermediates served in the wrong order, an extra unnecessary cert in the chain, or a CT-related warning. Re-export the chain bundle in the canonical order (leaf, then intermediates from issuing CA up, root excluded).
Multi-host failure patterns
MIN aggregation means one host taints the whole score. Common multi-host failures:
- Apex serves full chain, www serves leaf-only. Different vhosts with different cert files. Verify each vhost references fullchain, not cert.
- api.yourdomain.tld behind a different LB with an outdated cert. Different infrastructure paths produce different chains. Audit per-host.
- Internal subdomain accidentally exposed publicly with a self-signed cert. Either remove from public DNS or replace with a public cert.
- One host on an old commercial CA whose root has been distrusted. Migrate to a current CA.
Verify the fix
- For each sampled host listed in chain_validation_rows: openssl s_client -connect host:443 -servername host -verify_return_error < /dev/null. Look for "Verify return code: 0 (ok)" at the bottom.
- Count served certs per host: echo | openssl s_client -connect host:443 -servername host -showcerts 2>/dev/null | grep -c 'BEGIN CERTIFICATE'. Should be at least 2 (leaf + intermediate); 1 means leaf-only.
- ssllabs.com/ssltest reports chain validation per probed host, including ordering issues.
- Re-run the RedScore lookup. Pass requires strict-verify success on every sampled host.
Common pitfalls
- Worst-host scoring magnifies single failures. One legacy subdomain with a self-signed cert tanks the score for the whole domain. Inventory every public HTTPS host.
- Browser shows OK, RedScore fails. Modern browsers can recover via AIA fetching when intermediates are missing; strict clients (Python ssl, older mobile, IoT) cannot. The check uses strict verification; treat browser "locked" icon as not sufficient.
- CDN serves chain for proxied paths only. Some CDNs serve a clean chain through the proxy but origin still serves leaf-only on direct probes. If the check samples origin (or origin is in the resolved-host pool), the bad chain shows up.
- Cert renewed but old leaf still served. Reverse proxies and load balancers cache certs; reload after renewal so the renewed chain is in memory everywhere.
- Cross-signed root hierarchy gotchas. After major root rotations (DST Root CA X3 → ISRG Root X1 in 2021), some clients did not trust the new root for months. Refresh certbot or your ACME client regularly so renewals pull current cross-signs.
- Tied to SAN Hostname Match (in Web Application Security). The strict-verify signal is the same one used by the SAN sub-weight; if you fail one, you usually fail both. The verify_error string disambiguates which side is broken.
What to do next
See how these recommendations apply to your site's current scan results.
Scan domain