A Rust CLI to inspect TLS certificates and chains, with two subcommands:
- diag: diagnose a live server or a PEM bundle and validate the chain
- scaffold: build a full bundle from a leaf certificate file by fetching intermediates via AIA
cargo install --path .# Build
cargo build
# Run unit tests
cargo test
# Run locally without installing
cargo run -- diag -s google.com -p 443tls-doctor diag -h
Diagnose a live server or a PEM bundle
Usage: tls-doctor diag [OPTIONS] <--server <SERVER>|--file <FILE>>
Options:
  -s, --server <SERVER>  Domain name or IP of the server to connect to
  -f, --file <FILE>      PEM bundle file (one or more concatenated certificates)
  -p, --port <PORT>      Port of the server (default: 443) [default: 443]
      --insecure         Disable certificate verification (like -verify 0). Useful for inspecting invalid chains
  -h, --help             Print helptls-doctor scaffold -h
Scaffold a complete bundle from a leaf certificate file
Usage: tls-doctor scaffold --input <INPUT> --output <OUTPUT>
Options:
  -i, --input <INPUT>    Input leaf certificate file (PEM or DER)
  -o, --output <OUTPUT>  Output bundle destination (PEM); will be created/overwritten
  -h, --help             Print help- 
diag (server): - Opens a TLS connection to the host:port and collects the peer certificate and any provided intermediates.
- Orders the chain leaf → root (best effort), prints concise details for each certificate, and validates the chain against the OS trust store (OpenSSL default paths).
- Prints a summary: valid or issues with short explanations.
 
- 
diag (file): - Reads a PEM bundle, orders the chain, prints unrelated certs (if any), and performs the same validation against the OS trust store.
 
- 
scaffold: - Parses the input leaf certificate (PEM or DER).
- Extracts AIA caIssuers URIs from the certificate and iteratively fetches issuer certificates over HTTP(S).
- Accepts DER or PEM issuer responses (best effort), stops at a self-issued cert or when AIA data is missing.
- Writes the collected chain to the output PEM file (leaf first).
- Note: Roots are not “downloaded”; anchoring is expected to come from the system trust store when validating.
 
- 
TLS handshake fails (diag server): - Check host/port, firewall, and SNI correctness (use the DNS name you expect the cert for).
- If the server presents an invalid chain, add --insecureto still inspect it.
 
- 
“chain incomplete” or “unrelated certificate(s)” (diag file): - The input bundle likely mixes unrelated certs or is missing an intermediate. The tool orders what it can and reports extras separately.
 
- 
Validation fails but the chain looks correct: - Your OS trust store may not include the issuing root (corporate/private PKI). Install the CA at the OS level, or use --insecurefor inspection only.
 
- Your OS trust store may not include the issuing root (corporate/private PKI). Install the CA at the OS level, or use 
- 
scaffold finds no intermediates: - The leaf or its issuer may not include AIA caIssuers URIs (not mandatory). You may have to add intermediates manually.
 
- 
scaffold fetch errors/timeouts: - Check network connectivity and proxies. The HTTP client honors standard env vars like HTTP_PROXY/HTTPS_PROXY.
- Some AIA endpoints can rate-limit or be temporarily unavailable; retry later.
 
- Check network connectivity and proxies. The HTTP client honors standard env vars like 
- 
scaffold output is missing the root certificate: - By design, roots are not fetched online. Verification is expected to trust a system-installed root.
 
- 
Input format issues: - The tool accepts PEM or DER for the leaf and for fetched issuers. If an AIA endpoint serves PKCS#7 bundles, extracting certificates manually may be required.
 
Output includes for each certificate:
- Subject and Issuer
- Public Key algorithm and size
- SHA-256 fingerprint