{"record":{"id":"ee445a62217decac","repo":"basecamp/fizzy","slug":"unsupported-ec-curve-curve","errorCode":null,"errorMessage":"Unsupported EC curve: #{curve}","messagePattern":"Unsupported EC curve: #(.+?)","errorType":"exception","errorClass":"ActionPack::WebAuthn::UnsupportedKeyTypeError","httpStatus":null,"severity":"error","filePath":"lib/action_pack/web_authn/cose_key.rb","lineNumber":115,"sourceCode":"  # Returns an +OpenSSL::PKey::EC+ for EC2 keys, +OpenSSL::PKey::RSA+ for\n  # RSA keys, or an Ed25519 key for OKP keys, suitable for use with\n  # +OpenSSL::PKey#verify+.\n  #\n  # Raises +UnsupportedKeyTypeError+ if the key type, algorithm, or curve\n  # is not supported.\n  def to_openssl_key\n    case [ key_type, algorithm ]\n    when [ EC2, ES256 ] then build_ec2_es256_key\n    when [ OKP, EDDSA ] then build_okp_eddsa_key\n    when [ RSA, RS256 ] then build_rsa_rs256_key\n    else raise ActionPack::WebAuthn::UnsupportedKeyTypeError, \"Unsupported COSE key type/algorithm: #{key_type}/#{algorithm}\"\n    end\n  end\n\n  private\n    def build_ec2_es256_key\n      curve = parameters[EC2_CURVE_LABEL]\n      raise ActionPack::WebAuthn::UnsupportedKeyTypeError, \"Unsupported EC curve: #{curve}\" unless curve == P256\n\n      x = parameters[EC2_X_LABEL]\n      y = parameters[EC2_Y_LABEL]\n      raise ActionPack::WebAuthn::InvalidKeyError, \"Missing EC2 key coordinates\" if x.nil? || y.nil?\n      raise ActionPack::WebAuthn::InvalidKeyError, \"Invalid EC2 coordinate length\" unless x.bytesize == P256_COORDINATE_LENGTH && y.bytesize == P256_COORDINATE_LENGTH\n\n      # Uncompressed point format: 0x04 || x || y\n      public_key_bytes = [ UNCOMPRESSED_POINT_MARKER, *x.bytes, *y.bytes ].pack(\"C*\")\n\n      asn1 = OpenSSL::ASN1::Sequence([\n        OpenSSL::ASN1::Sequence([\n          OpenSSL::ASN1::ObjectId(\"id-ecPublicKey\"),\n          OpenSSL::ASN1::ObjectId(\"prime256v1\")\n        ]),\n        OpenSSL::ASN1::BitString(public_key_bytes)\n      ])\n\n      OpenSSL::PKey::EC.new(asn1.to_der)","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/basecamp/fizzy/blob/7aabe7458060d8a1759a53b7ede39e74e6c0b20d/lib/action_pack/web_authn/cose_key.rb#L97-L133","documentation":"For EC2 keys the library only builds P-256 (prime256v1) keys: the COSE curve label (-1) must equal 1. Any other curve value — 2 (P-384), 3 (P-521), 0/nil (missing) — raises UnsupportedKeyTypeError with the value interpolated.","triggerScenarios":"A credential attested as ES256 whose COSE map carries curve 2 or 3 (mismatched metadata), a P-384 smart-card credential, or a truncated COSE map where label -1 is absent so curve is nil.","commonSituations":"Authenticators or middleware that emit ES384 keys while labeling the algorithm ES256; conformance-test vectors using exotic curves; hand-assembled COSE maps missing the crv (-1) entry.","solutions":["Restrict client registration to ES256/RS256/EdDSA via pubKeyCredParams so non-P-256 EC keys are never created.","Pre-check parameters[-1] == 1 before calling to_openssl_key and reject with a specific 'curve not supported' message.","Rescue UnsupportedKeyTypeError at registration and ask the user to use a different authenticator.","Verify the COSE map has labels 1, 3, -1, -2, -3 before conversion — missing labels produce confusing downstream errors."],"exampleFix":"# before\nkey = cose_key.to_openssl_key # raises for curve 2/3/nil\n\n# after — gate on the supported curve first\nunless cose_key.parameters[CoseKey::EC2_CURVE_LABEL] == CoseKey::P256\n  return render json: { error: 'credential curve not supported' }, status: :bad_request\nend\nkey = cose_key.to_openssl_key","handlingStrategy":"validation","validationCode":"if cose_key.key_type == ActionPack::WebAuthn::CoseKey::EC2 && cose_key.parameters[ActionPack::WebAuthn::CoseKey::EC2_CURVE_LABEL] != ActionPack::WebAuthn::CoseKey::P256\n  return render json: { error: 'credential curve not supported' }, status: :bad_request\nend","typeGuard":"def supported_ec2_curve?(cose_key)\n  cose_key.parameters[ActionPack::WebAuthn::CoseKey::EC2_CURVE_LABEL] == ActionPack::WebAuthn::CoseKey::P256\nend","tryCatchPattern":"begin\n  key = cose_key.to_openssl_key\nrescue ActionPack::WebAuthn::UnsupportedKeyTypeError => e\n  render json: { error: e.message }, status: :bad_request\nend","preventionTips":["Pin pubKeyCredParams to ES256/RS256/EdDSA; do not advertise ES384/ES512 unless the server verifies them.","Validate the COSE map has integer labels 1, 3, -1 before conversion.","Rescue UnsupportedKeyTypeError distinctly from InvalidKeyError: unsupported is a capability mismatch, invalid is corrupt data."],"tags":["webauthn","cose","elliptic-curve","cryptography"],"backgroundTag":"unsupported-elliptic-curve","analyzedSha":"7aabe7458060d8a1759a53b7ede39e74e6c0b20d","analyzedAt":"2026-08-21T18:33:25.349Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}