{"record":{"id":"b197e74ab4923355","repo":"slackhq/nebula","slug":"invalid-curve-s","errorCode":null,"errorMessage":"invalid curve: %s","messagePattern":"invalid curve: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cert/cert_v1.go","lineNumber":160,"sourceCode":"\t\t\t// the call to PublicKey below will panic slice bounds out of range otherwise\n\t\t\tif len(key) != ed25519.PrivateKeySize {\n\t\t\t\treturn fmt.Errorf(\"key was not 64 bytes, is invalid ed25519 private key\")\n\t\t\t}\n\n\t\t\tif !ed25519.PublicKey(c.details.publicKey).Equal(ed25519.PrivateKey(key).Public()) {\n\t\t\t\treturn fmt.Errorf(\"public key in cert and private key supplied don't match\")\n\t\t\t}\n\t\tcase Curve_P256:\n\t\t\tprivkey, err := ecdh.P256().NewPrivateKey(key)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"cannot parse private key as P256: %w\", err)\n\t\t\t}\n\t\t\tpub := privkey.PublicKey().Bytes()\n\t\t\tif !bytes.Equal(pub, c.details.publicKey) {\n\t\t\t\treturn fmt.Errorf(\"public key in cert and private key supplied don't match\")\n\t\t\t}\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"invalid curve: %s\", curve)\n\t\t}\n\t\treturn nil\n\t}\n\n\tvar pub []byte\n\tswitch curve {\n\tcase Curve_CURVE25519:\n\t\tvar err error\n\t\tpub, err = curve25519.X25519(key, curve25519.Basepoint)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\tcase Curve_P256:\n\t\tprivkey, err := ecdh.P256().NewPrivateKey(key)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tpub = privkey.PublicKey().Bytes()","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/cert/cert_v1.go#L142-L178","documentation":"VerifyPrivateKey validates the curve identifier before processing the key. If curve is neither Curve_Ed25519 nor Curve_P256, neither switch branch runs and the function returns 'invalid curve'. This guards against calling the verifier with an unsupported or misspelled curve value.","triggerScenarios":"Calling (*certificateV1).VerifyPrivateKey with curve set to anything other than Curve_Ed25519 or Curve_P256 (e.g. Curve_UNSET, zero value, or a curve value from a different cert version).","commonSituations":"Passing the certificate's raw protobuf curve enum when it is unset; copying code written for cert v2 curve values; forgetting to set the curve field on a synthesized certificate.","solutions":["Pass cert.Curve_Ed25519 or cert.Curve_P256 explicitly as the curve argument","Read the intended curve from the certificate details and default sensibly if unset","Check whether you are mixing curve constants from a different certificate API/version","Log/print the curve value being passed to confirm what is reaching the function"],"exampleFix":"// before\nerr := cert.VerifyPrivateKey(key, 0 /* unset curve */, keyBytes)\n// after\nerr := cert.VerifyPrivateKey(key, cert.Curve_P256, keyBytes)","handlingStrategy":"validation","validationCode":"func isSupportedCurve(curve cert.Curve) bool {\n    return curve == cert.Curve_Ed25519 || curve == cert.Curve_P256\n}\nif !isSupportedCurve(curveArg) {\n    return fmt.Errorf(\"caller passed unsupported curve %v\", curveArg)\n}\nerr := c.VerifyPrivateKey(key, curveArg, keyBytes)","typeGuard":"func hasCurveSet(curve cert.Curve) bool {\n    return curve == cert.Curve_Ed25519 || curve == cert.Curve_P256\n}","tryCatchPattern":"if err := c.VerifyPrivateKey(key, curveArg, keyBytes); err != nil {\n    var badCurve = fmt.Errorf(\"invalid curve %v: must be Curve_Ed25519 or Curve_P256\", curveArg)\n    if strings.Contains(err.Error(), \"invalid curve\") {\n        return badCurve\n    }\n    return err\n}","preventionTips":["Always pass named constants (Curve_Ed25519/Curve_P256), never raw ints","Initialize curve fields explicitly when constructing certificates","Watch for unset (zero) enum values when reading from protobuf","Add a caller-side curve allowlist check"],"tags":["certificate","curve","argument-validation"],"backgroundTag":"invalid-curve","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"}