router-for-me/CLIProxyAPI · critical

home ca fingerprint mismatch

Error message

home ca fingerprint mismatch

What it means

Thrown by verifyCACertificatePEM in internal/home/certificate.go when the SHA-256 fingerprint of the supplied CA PEM does not match the normalized expected fingerprint. This is a trust-on-first-use pin: the CA file on disk differs from the CA the deployment pinned. Note comparison is exact-string on the lowercased hex digest, so any byte difference in the certificate fails.

Source

Thrown at internal/home/certificate.go:194

func verifyCACertificateFile(path string, expectedFingerprint string) error {
	raw, errRead := os.ReadFile(path)
	if errRead != nil {
		return errRead
	}
	return verifyCACertificatePEM(raw, expectedFingerprint)
}

func verifyCACertificatePEM(raw []byte, expectedFingerprint string) error {
	actual, errFingerprint := certificateFingerprintPEM(raw)
	if errFingerprint != nil {
		return errFingerprint
	}
	expected := normalizeFingerprint(expectedFingerprint)
	if expected == "" {
		return fmt.Errorf("home ca fingerprint is required")
	}
	if actual != expected {
		return fmt.Errorf("home ca fingerprint mismatch")
	}
	return nil
}

func certificateFingerprintPEM(raw []byte) (string, error) {
	block, _ := pem.Decode(raw)
	if block == nil || block.Type != "CERTIFICATE" {
		return "", fmt.Errorf("home ca certificate pem is invalid")
	}
	cert, errParse := x509.ParseCertificate(block.Bytes)
	if errParse != nil {
		return "", errParse
	}
	sum := sha256.Sum256(cert.Raw)
	return hex.EncodeToString(sum[:]), nil
}

func normalizeFingerprint(fingerprint string) string {

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Recompute the fingerprint of the CA actually deployed: openssl x509 -in ca.pem -noout -fingerprint -sha256, and update ca-fingerprint in config
  2. If the CA was rotated legitimately, redistribute the new ca.pem and its fingerprint to all clients
  3. If the CA file is wrong, restore the original ca.pem that matches the pinned fingerprint

Example fix

# before
home:
  ca-cert: /etc/cliproxy/ca.pem
  ca-fingerprint: "oldhash..."

# after — after CA rotation
home:
  ca-cert: /etc/cliproxy/new-ca.pem
  ca-fingerprint: "$(openssl x509 -in /etc/cliproxy/new-ca.pem -noout -fingerprint -sha256 | cut -d= -f2 | tr -d : | tr A-F a-f)"
Defensive patterns

Strategy: validation

Validate before calling

// pin check at startup, before the client relies on the CA
fp := strings.ToLower(hex.EncodeToString(certSHA256(caPEM)))
if fp != normalize(cfg.CAFingerprint) {
    log.Fatalf("ca.pem fingerprint drift: file=%s pinned=%s — rotate config or restore ca.pem", fp, cfg.CAFingerprint)
}

Try / catch

if err != nil && strings.Contains(err.Error(), "home ca fingerprint mismatch") {
    // do NOT retry: trust mismatch requires operator decision (new fingerprint or restored CA)
    haltAndAlert("home CA trust mismatch")
}

Prevention

When it happens

Trigger: CA certificate file at the configured path was rotated, re-issued, or regenerated (different key) while the expected fingerprint stayed the same; wrong CA file copied into auths/ or the cert directory; fingerprint recorded from a different cert (e.g. leaf instead of CA).

Common situations: Home server rotated its CA and clients still pin the old fingerprint; staging fingerprint left in production config; someone re-ran the CA generation step and overwrote ca.pem; fingerprint copied with truncation or extra characters is handled by normalization but a wrong-hash is not.

Related errors


AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15). Data as JSON: /api/errors/8c5f68eb5507087c. Report an issue: GitHub.