{"record":{"id":"ae7843d4fd54a1c8","repo":"slackhq/nebula","slug":"errfingerprintmismatch","errorCode":"ErrFingerprintMismatch","errorMessage":"certificate fingerprint did not match","messagePattern":"certificate fingerprint did not match","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cert/errors.go","lineNumber":15,"sourceCode":"package cert\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n)\n\nvar (\n\tErrBadFormat                  = errors.New(\"bad wire format\")\n\tErrRootExpired                = errors.New(\"root certificate is expired\")\n\tErrExpired                    = errors.New(\"certificate is expired\")\n\tErrNotCA                      = errors.New(\"certificate is not a CA\")\n\tErrNotSelfSigned              = errors.New(\"certificate is not self-signed\")\n\tErrBlockListed                = errors.New(\"certificate is in the block list\")\n\tErrFingerprintMismatch        = errors.New(\"certificate fingerprint did not match\")\n\tErrSignatureMismatch          = errors.New(\"certificate signature did not match\")\n\tErrInvalidPublicKey           = errors.New(\"invalid public key\")\n\tErrInvalidPrivateKey          = errors.New(\"invalid private key\")\n\tErrPublicPrivateCurveMismatch = errors.New(\"public key does not match private key curve\")\n\tErrPublicPrivateKeyMismatch   = errors.New(\"public key and private key are not a pair\")\n\tErrPrivateKeyEncrypted        = errors.New(\"private key must be decrypted\")\n\tErrCaNotFound                 = errors.New(\"could not find ca for the certificate\")\n\tErrUnknownVersion             = errors.New(\"certificate version unrecognized\")\n\tErrCertPubkeyPresent          = errors.New(\"certificate has unexpected pubkey present\")\n\tErrCurveMismatch              = errors.New(\"certificate curve does not match CA\")\n\n\tErrInvalidPEMBlock                   = errors.New(\"input did not contain a valid PEM encoded block\")\n\tErrInvalidPEMCertificateBanner       = errors.New(\"bytes did not contain a proper certificate banner\")\n\tErrInvalidPEMX25519PublicKeyBanner   = errors.New(\"bytes did not contain a proper X25519 public key banner\")\n\tErrInvalidPEMX25519PrivateKeyBanner  = errors.New(\"bytes did not contain a proper X25519 private key banner\")\n\tErrInvalidPEMEd25519PublicKeyBanner  = errors.New(\"bytes did not contain a proper Ed25519 public key banner\")\n\tErrInvalidPEMEd25519PrivateKeyBanner = errors.New(\"bytes did not contain a proper Ed25519 private key banner\")\n","sourceCodeStart":1,"sourceCodeEnd":33,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/cert/errors.go#L1-L33","documentation":"ErrFingerprintMismatch is returned by verify when the caller supplied an expected signer fingerprint and the fingerprint of the CA that actually signed the certificate does not equal it. This guards against trusting a different (possibly malicious) CA within the pool.","triggerScenarios":"CAPool.verify (cert/ca_pool.go:236) when len(signerFp) > 0 and the resolved signer's Fingerprint differs from the provided signerFp — i.e., VerifyCertificate was given a fingerprint hint that matches a different CA in the pool.","commonSituations":"The pinned CA fingerprint in config doesn't match the ca.crt actually distributed (stale ca.crt after rotation); multiple CAs in the pool and the wrong one signed the cert; copy/paste error in fingerprint configuration.","solutions":["Compare the pinned fingerprint with the actual CA's Fingerprint value and update the config or the ca.crt so they agree.","Re-sign the certificate with the CA whose fingerprint is pinned.","Clear the fingerprint hint if pinning is not intended (only pass the expected fingerprint when you mean to pin).","Print both fingerprints (expected vs signer.Fingerprint) when debugging to spot rotation drift."],"exampleFix":"// before\nvalid, err := pool.VerifyCertificate(c, oldCaFp, \"\") // CA was rotated\n\n// after\nnewCaFp := hex.EncodeToString(currentCA.Fingerprint)\nvalid, err := pool.VerifyCertificate(c, newCaFp, \"\")","handlingStrategy":"validation","validationCode":"expectedFp := config.PinnedCAFingerprint\nif expectedFp != \"\" && expectedFp != hex.EncodeToString(ca.Fingerprint) {\n    return fmt.Errorf(\"pinned CA fingerprint mismatch: update config after rotation\")\n}","typeGuard":"func fingerprintMatches(signer *cert.CachedCertificate, expectedFp string) bool {\n    return expectedFp == \"\" || expectedFp == signer.Fingerprint\n}","tryCatchPattern":"if _, err := pool.VerifyCertificate(c, pinnedFp, \"\"); errors.Is(err, cert.ErrFingerprintMismatch) {\n    return fmt.Errorf(\"CA rotated? pinned fp %s != signer fp %s\", pinnedFp, signer.Fingerprint)\n}","preventionTips":["Update pinned fingerprints whenever ca.crt is rotated.","Log both expected and actual fingerprints on mismatch.","Only pass a fingerprint hint when you intentionally pin a specific CA."],"tags":["certificate","fingerprint","pinning"],"backgroundTag":"certificate-fingerprint-mismatch","analyzedSha":"dd8f660c0ac37903ec4080ca4d3c861ba9342ceb","analyzedAt":"2026-09-03T11:13:55.444Z","contentChangedAt":"2026-09-03T11:13:55.444Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}