{"record":{"id":"14b3cd0e9d7b427e","repo":"odoo/odoo","slug":"attestation-statement-was-missing-algorithm-andro","errorCode":null,"errorMessage":"Attestation statement was missing algorithm (Android Key)","messagePattern":"Attestation statement was missing algorithm \\(Android Key\\)","errorType":"exception","errorClass":"InvalidRegistrationResponse","httpStatus":null,"severity":"error","filePath":"addons/auth_passkey/_vendor/webauthn/registration/formats/android_key.py","lineNumber":59,"sourceCode":"    attestation_statement: AttestationStatement,\n    attestation_object: bytes,\n    client_data_json: bytes,\n    credential_public_key: bytes,\n    pem_root_certs_bytes: List[bytes],\n) -> bool:\n    \"\"\"Verify an \"android-key\" attestation statement\n\n    See https://www.w3.org/TR/webauthn-2/#sctn-android-key-attestation\n\n    Also referenced: https://source.android.com/security/keystore/attestation\n    \"\"\"\n    if not attestation_statement.sig:\n        raise InvalidRegistrationResponse(\n            \"Attestation statement was missing signature (Android Key)\"\n        )\n\n    if not attestation_statement.alg:\n        raise InvalidRegistrationResponse(\n            \"Attestation statement was missing algorithm (Android Key)\"\n        )\n\n    if not attestation_statement.x5c:\n        raise InvalidRegistrationResponse(\"Attestation statement was missing x5c (Android Key)\")\n\n    # Validate certificate chain\n    try:\n        # Include known root certificates for this attestation format\n        pem_root_certs_bytes.append(google_hardware_attestation_root_1)\n        pem_root_certs_bytes.append(google_hardware_attestation_root_2)\n\n        validate_certificate_chain(\n            x5c=attestation_statement.x5c,\n            pem_root_certs_bytes=pem_root_certs_bytes,\n        )\n    except InvalidCertificateChain as err:\n        raise InvalidRegistrationResponse(f\"{err} (Android Key)\")","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/odoo/odoo/blob/1e661df964b1b264c9cef3ab28430d4785be3fda/addons/auth_passkey/_vendor/webauthn/registration/formats/android_key.py#L41-L77","documentation":"Raised by the vendored py_webauthn Android Key attestation verifier when the attStmt map from the authenticator has no 'alg' entry. Per WebAuthn Level 2 sctn-android-key-attestation, the algorithm identifier is mandatory because the RP must know which COSE algorithm the attestation signature uses. The library rejects the response before any crypto work since it cannot pick a verification algorithm.","triggerScenarios":"verify_android_key_attestation() (or register_credentials()/verify_registration_response() with attestation format 'android-key') receives an attestation_object whose CBOR attStmt lacks the key 'alg' (e.g. attStmt = {'sig': ..., 'x5c': [...]} only). Typical of malformed hand-crafted responses or authenticators/emulators emitting non-conforming android-key statements.","commonSituations":"Testing with recorded/static registration responses that were truncated; x5c copied from key attestation docs but alg omitted; intermediate proxies or CBOR re-encoders dropping zero/optional-looking fields; authenticator firmware bugs.","solutions":["Inspect the raw attestation_object CBOR and confirm attStmt contains 'alg' alongside 'sig' and 'x5c'","Regenerate the registration response from a real Android device with hardware key attestation enabled (strongbox/TEE)","If you build test fixtures, include alg: -7 (ES256) or -257 (RS256) as produced by the device","If the authenticator consistently omits alg, report an authenticator bug and consider accepting 'none'/self-attestation instead of requesting android-key attestation"],"exampleFix":"# before: fixture missing alg\natt_stmt = {\"sig\": sig_bytes, \"x5c\": [der_cert]}\n\n# after: include the COSE algorithm the device used\natt_stmt = {\"alg\": -7, \"sig\": sig_bytes, \"x5c\": [der_cert]}","handlingStrategy":"validation","validationCode":"# Before verify_registration_response(), sanity-check attStmt keys\nimport cbor2\n\ndef att_stmt_has_required_keys(attestation_object: bytes, fmt: str) -> bool:\n    att = cbor2.loads(attestation_object)\n    if att.get(\"fmt\") != fmt:\n        return False\n    stmt = att.get(\"attStmt\", {})\n    required = {\"sig\", \"alg\", \"x5c\"} if fmt == \"android-key\" else set()\n    return required.issubset(stmt)","typeGuard":"def is_complete_android_key_stmt(att: dict) -> bool:\n    stmt = att.get(\"attStmt\") or {}\n    return (\n        att.get(\"fmt\") == \"android-key\"\n        and isinstance(stmt.get(\"sig\"), bytes)\n        and isinstance(stmt.get(\"alg\"), int)\n        and isinstance(stmt.get(\"x5c\"), list)\n        and len(stmt[\"x5c\"]) > 0\n    )","tryCatchPattern":"try:\n    verify_registration_response(...)\nexcept InvalidRegistrationResponse as e:\n    if \"missing algorithm (Android Key)\" in str(e):\n        log.security(\"malformed android-key attestation\", att_stmt_keys=sorted(stmt))\n    raise","preventionTips":["Validate attStmt structure per format before calling the verifier","Keep client and py_webauthn versions aligned so field expectations match","Never hand-assemble attestation objects; always use device output"],"tags":["webauthn","android-key","attestation","registration","cbor"],"backgroundTag":null,"analyzedSha":"1e661df964b1b264c9cef3ab28430d4785be3fda","analyzedAt":"2026-08-15T05:22:16.142Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}