{"record":{"id":"5ea9bbede593fe05","repo":"slackhq/nebula","slug":"no-certificate","errorCode":null,"errorMessage":"no certificate","messagePattern":"no certificate","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cert/ca_pool.go","lineNumber":159,"sourceCode":"\tncp.certBlocklist = make(map[string]struct{})\n}\n\n// IsBlocklisted tests the provided fingerprint against the pools blocklist.\n// Returns true if the fingerprint is blocked.\nfunc (ncp *CAPool) IsBlocklisted(fingerprint string) bool {\n\tif _, ok := ncp.certBlocklist[fingerprint]; ok {\n\t\treturn true\n\t}\n\n\treturn false\n}\n\n// VerifyCertificate verifies the certificate is valid and is signed by a trusted CA in the pool.\n// If the certificate is valid then the returned CachedCertificate can be used in subsequent verification attempts\n// to increase performance.\nfunc (ncp *CAPool) VerifyCertificate(now time.Time, c Certificate) (*CachedCertificate, error) {\n\tif c == nil {\n\t\treturn nil, fmt.Errorf(\"no certificate\")\n\t}\n\tfp, err := c.Fingerprint()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"could not calculate fingerprint to verify: %w\", err)\n\t}\n\n\tsigner, err := ncp.verify(c, now, fp, \"\")\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Pre nebula v1.10.3 could generate signatures in either high or low s form and validation\n\t// of signatures allowed for either. Nebula v1.10.3 and beyond clamps signature generation to low-s form\n\t// but validation still allows for either. Since a change in the signature bytes affects the fingerprint, we\n\t// need to test both forms until such a time comes that we enforce low-s form on signature validation.\n\tfp2, err := CalculateAlternateFingerprint(c)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"could not calculate alternate fingerprint to verify: %w\", err)","sourceCodeStart":141,"sourceCodeEnd":177,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/cert/ca_pool.go#L141-L177","documentation":"CAPool.VerifyCertificate returns the plain error 'no certificate' when the passed Certificate is nil. Verification cannot proceed without a certificate, and the nil check short-circuits before any fingerprinting or chain validation.","triggerScenarios":"Calling VerifyCertificate(now, c) with c == nil — typically when a decoded certificate variable was never populated because PEM decoding or certificate parsing failed upstream.","commonSituations":"Ignoring errors from earlier ParseCertificate/PEM decode steps and passing the nil result on, or optional certificate lookups (e.g. from a handshake cache) returning nil.","solutions":["Check the certificate for nil before calling VerifyCertificate","Handle errors from the certificate parsing/decoding step so a nil cert is never passed","Log and reject the connection early when no peer certificate is available"],"exampleFix":"// before\ncc, err := pool.VerifyCertificate(now, parsedCert) // parsedCert may be nil\n// after\nif parsedCert == nil {\n    return fmt.Errorf(\"peer did not present a certificate\")\n}\ncc, err := pool.VerifyCertificate(now, parsedCert)","handlingStrategy":"type-guard","validationCode":"if c == nil {\n    return fmt.Errorf(\"no peer certificate available for verification\")\n}\n_, err := pool.VerifyCertificate(now, c)","typeGuard":"func hasCertificate(c cert.Certificate) bool {\n    return c != nil\n}","tryCatchPattern":"cc, err := pool.VerifyCertificate(now, c)\nif err != nil {\n    if err.Error() == \"no certificate\" {\n        log.Warn(\"peer presented no certificate; rejecting handshake\")\n        return err\n    }\n    return err\n}","preventionTips":["Always check parse/decode errors before using a Certificate variable","Treat nil certificates from handshake caches as a hard rejection","Fail closed: never skip verification when the certificate is missing"],"tags":["certificate","nil-check","ca-pool"],"backgroundTag":"nil-certificate","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"}