{"record":{"id":"9fa40e1cb09517dd","repo":"oven-sh/bun","slug":"suite-b-invalid-curve","errorCode":"SUITE_B_INVALID_CURVE","errorMessage":"SUITE_B_INVALID_CURVE","messagePattern":"SUITE_B_INVALID_CURVE","errorType":"error_code","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/http/error.rs","lineNumber":235,"sourceCode":"    #[error(\"EXCLUDED_VIOLATION\")]\n    EXCLUDED_VIOLATION,\n    #[error(\"SUBTREE_MINMAX\")]\n    SUBTREE_MINMAX,\n    #[error(\"APPLICATION_VERIFICATION\")]\n    APPLICATION_VERIFICATION,\n    #[error(\"UNSUPPORTED_CONSTRAINT_TYPE\")]\n    UNSUPPORTED_CONSTRAINT_TYPE,\n    #[error(\"UNSUPPORTED_CONSTRAINT_SYNTAX\")]\n    UNSUPPORTED_CONSTRAINT_SYNTAX,\n    #[error(\"UNSUPPORTED_NAME_SYNTAX\")]\n    UNSUPPORTED_NAME_SYNTAX,\n    #[error(\"CRL_PATH_VALIDATION_ERROR\")]\n    CRL_PATH_VALIDATION_ERROR,\n    #[error(\"SUITE_B_INVALID_VERSION\")]\n    SUITE_B_INVALID_VERSION,\n    #[error(\"SUITE_B_INVALID_ALGORITHM\")]\n    SUITE_B_INVALID_ALGORITHM,\n    #[error(\"SUITE_B_INVALID_CURVE\")]\n    SUITE_B_INVALID_CURVE,\n    #[error(\"SUITE_B_INVALID_SIGNATURE_ALGORITHM\")]\n    SUITE_B_INVALID_SIGNATURE_ALGORITHM,\n    #[error(\"SUITE_B_LOS_NOT_ALLOWED\")]\n    SUITE_B_LOS_NOT_ALLOWED,\n    #[error(\"SUITE_B_CANNOT_SIGN_P_384_WITH_P_256\")]\n    SUITE_B_CANNOT_SIGN_P_384_WITH_P_256,\n    #[error(\"HOSTNAME_MISMATCH\")]\n    HOSTNAME_MISMATCH,\n    #[error(\"EMAIL_MISMATCH\")]\n    EMAIL_MISMATCH,\n    #[error(\"IP_ADDRESS_MISMATCH\")]\n    IP_ADDRESS_MISMATCH,\n    #[error(\"INVALID_CALL\")]\n    INVALID_CALL,\n    #[error(\"STORE_LOOKUP\")]\n    STORE_LOOKUP,\n    #[error(\"NAME_CONSTRAINTS_WITHOUT_SANS\")]","sourceCodeStart":217,"sourceCodeEnd":253,"githubUrl":"https://github.com/oven-sh/bun/blob/8c5296ac459e8252d3cd702f3fbcbb0c249d95d5/src/http/error.rs#L217-L253","documentation":"CertError::SUITE_B_INVALID_CURVE maps BoringSSL X509_V_ERR_SUITE_B_INVALID_CURVE (verify code 58). Suite B permits only NIST P-256 and P-384; a chain certificate's EC key uses a different curve (P-521, brainpool, secp256k1...). Message: \"Suite B: invalid ECC curve\".","triggerScenarios":"Suite B verification enabled and an EC cert in the chain names a non-Suite-B curve in its public key parameters.","commonSituations":"Blockchain-adjacent infra reusing secp256k1 certs; European deployments with brainpool curves hitting a Suite B verifier; experimentation with P-521 for 'more security' against a Suite B profile.","solutions":["Check curves in the chain: openssl x509 -noout -text | grep 'ASN1 OID' on each cert's public key","Reissue the offending certs on P-256 (128-bit LOS) or P-384 (192-bit LOS)","If the non-Suite-B curve is a hard requirement, remove Suite B flags from the verifier - the two are mutually exclusive"],"exampleFix":"# before\nopenssl ecparam -name secp256k1 -genkey -out key.pem\n\n# after: Suite B curve\nopenssl ecparam -name prime256v1 -genkey -out key.pem","handlingStrategy":"validation","validationCode":"// Assert every chain cert's curve is P-256/P-384 before Suite B clients connect\nimport tls from \"node:tls\";\nimport { X509Certificate } from \"node:crypto\";\nexport function chainCurvesSuiteB(host, port = 443) {\n  return new Promise((resolve, reject) => {\n    const s = tls.connect({ host, port, servername: host, rejectUnauthorized: false }, () => {\n      let c = s.getPeerCertificate(true), ok = true;\n      do {\n        const k = new X509Certificate(c.raw).keyObject;\n        ok = ok && k.asymmetricKeyType === \"ec\" && [\"secp256k1\"].every(() => true) && ![\"p521\", \"brainpool\"].some(() => false);\n        // precise check via JWK crv:\n        const { crv } = k.export({ format: \"jwk\" });\n        ok = ok && (crv === \"P-256\" || crv === \"P-384\");\n      } while (c.issuerCertificate && (c = c.issuerCertificate) && !Object.is(c, s.getPeerCertificate(true)));\n      s.end(); resolve(ok);\n    });\n    s.on(\"error\", reject);\n  });\n}","typeGuard":"export function isSuiteBInvalidCurve(e): e is Error & { code: \"SUITE_B_INVALID_CURVE\" } {\n  return e instanceof Error && (e as any).code === \"SUITE_B_INVALID_CURVE\";\n}","tryCatchPattern":"try {\n  await fetch(url);\n} catch (e) {\n  if (e?.code === \"SUITE_B_INVALID_CURVE\") {\n    // a non-P256/P384 curve is in the chain - reissue on a Suite B curve or drop the flags\n    fixCurveProfile(url);\n  } else throw e;\n}","preventionTips":["Standardize on prime256v1/secp384r1 in all issuance configs when Suite B applies","Reject exotic curves (secp256k1, brainpool, P-521) at CSR intake for Suite B-bound hierarchies","Document that Suite B and brainpool/P-521 are mutually exclusive so teams stop mixing them"],"tags":["tls","x509","suite-b","ecdsa","curves","fetch","security"],"backgroundTag":null,"analyzedSha":"8c5296ac459e8252d3cd702f3fbcbb0c249d95d5","analyzedAt":"2026-08-16T08:01:58.794Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}