{"record":{"id":"bcf6961437fe5b42","repo":"slackhq/nebula","slug":"v1-certificate-already-found-in-pki-cert","errorCode":null,"errorMessage":"v1 certificate already found in pki.cert","messagePattern":"v1 certificate already found in pki\\.cert","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pki.go","lineNumber":347,"sourceCode":"\t\t}\n\t}\n\n\tvar crt, v1, v2 cert.Certificate\n\tfor {\n\t\t// Load the certificate\n\t\tcrt, rawCert, err = loadCertificate(rawCert)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tif fips140.Enforced() && crt.Curve() != cert.Curve_P256 {\n\t\t\treturn nil, fmt.Errorf(\"pki: use of %s is not allowed in FIPS 140-only mode\", crt.Curve())\n\t\t}\n\n\t\tswitch crt.Version() {\n\t\tcase cert.Version1:\n\t\t\tif v1 != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"v1 certificate already found in pki.cert\")\n\t\t\t}\n\t\t\tv1 = crt\n\t\tcase cert.Version2:\n\t\t\tif v2 != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"v2 certificate already found in pki.cert\")\n\t\t\t}\n\t\t\tv2 = crt\n\t\tdefault:\n\t\t\treturn nil, fmt.Errorf(\"unknown certificate version %v\", crt.Version())\n\t\t}\n\n\t\tif len(rawCert) == 0 || strings.TrimSpace(string(rawCert)) == \"\" {\n\t\t\tbreak\n\t\t}\n\t}\n\n\tif v1 == nil && v2 == nil {\n\t\treturn nil, errors.New(\"no certificates found in pki.cert\")","sourceCodeStart":329,"sourceCodeEnd":365,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/pki.go#L329-L365","documentation":"pki.cert may contain a chain of certificates, but at most one v1 certificate and one v2 certificate are allowed. If a second cert.Version1 certificate is encountered during parsing, this error is returned to reject the malformed file.","triggerScenarios":"reloadCerts -> newCertStateFromConfig when pki.cert contains two or more v1-format certificates, typically from concatenating two complete cert files or appending a renewed cert of the same version instead of replacing it.","commonSituations":"Operators concatenating old and new certs during rotation; shell redirection with `>>` instead of `>` overwriting pki.cert; packaging scripts bundling multiple intermediates of the same version; copy-paste mishaps joining two PEM blobs.","solutions":["Edit pki.cert to keep exactly one v1 certificate (plus at most one v2) and remove the duplicate.","Regenerate pki.cert cleanly from the single intended certificate file.","Fix any `cat old.cert >> pki.cert` rotation scripts to use atomic replace instead of append.","Verify afterwards with openssl/nebula-cert tooling that the file parses as a single chain."],"exampleFix":"# before (rotating)\ncat new.cert >> /etc/nebula/pki.cert\n# after (rotating)\ninstall -m 0644 new.cert /etc/nebula/pki.cert","handlingStrategy":"validation","validationCode":"// Before reload: count v1/v2 PEM blocks in pki.cert\nfunc checkSingleCerts(raw []byte) error {\n  rest := raw; v1, v2 := 0, 0\n  for len(rest) > 0 {\n    var crt *x509.Certificate\n    crt, rest, _ = parseOne(rest)\n    switch crt.Version {\n    case 1: v1++\n    case 2: v2++\n    }\n    if v1 > 1 { return errors.New(\"pki.cert contains multiple v1 certificates\") }\n    if v2 > 1 { return errors.New(\"pki.cert contains multiple v2 certificates\") }\n  }\n  return nil\n}","typeGuard":null,"tryCatchPattern":"cs, err := newCertStateFromConfig(...)\nif err != nil {\n  if strings.Contains(err.Error(), \"already found in pki.cert\") {\n    return fmt.Errorf(\"pki.cert has duplicate certs; rebuild it as a single chain: %w\", err)\n  }\n  return err\n}","preventionTips":["Replace pki.cert atomically on rotation (install/mv), never append with >>.","Build pki.cert from a single source of truth in automation (one template, one cert).","After any cert change, parse the file and assert <=1 v1 and <=1 v2 before reload.","Review shell scripts that touch pki.cert for redirection mistakes."],"tags":["certificate","config","duplicate","pki"],"backgroundTag":"duplicate-certificate-in-chain","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"}