{"record":{"id":"a4845d52d87f4b4e","repo":"odoo/odoo","slug":"attestation-statement-was-missing-signature-andro","errorCode":null,"errorMessage":"Attestation statement was missing signature (Android Key)","messagePattern":"Attestation statement was missing signature \\(Android Key\\)","errorType":"exception","errorClass":"InvalidRegistrationResponse","httpStatus":null,"severity":"error","filePath":"addons/auth_passkey/_vendor/webauthn/registration/formats/android_key.py","lineNumber":54,"sourceCode":"from ....webauthn.helpers.structs import AttestationStatement\n\n\ndef verify_android_key(\n    *,\n    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(","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/odoo/odoo/blob/1e661df964b1b264c9cef3ab28430d4785be3fda/addons/auth_passkey/_vendor/webauthn/registration/formats/android_key.py#L36-L72","documentation":"While verifying an 'android-key' attestation statement, the sig component is absent. Per the Android Key attestation format, sig (the signature over the verification data) is mandatory; without it there is nothing to verify and the registration is rejected.","triggerScenarios":"Calling verify_android_key_format with an attestation_object whose attStmt lacks 'sig' — hand-built attestation objects in tests, a truncated CBOR attestation, or an authenticator/compatibility layer that emits incomplete android-key statements.","commonSituations":"Test fixtures hand-crafting attStmt dicts and forgetting 'sig'; clients sending base64 (not base64url) attestationObject so CBOR parsing partially fails; non-Google devices emitting malformed android-key statements.","solutions":["Send the authenticatorObject verbatim from cred.response.attestationObject (cred.toJSON())","In tests, generate realistic android-key attestations via a virtual authenticator rather than hand-building the CBOR","Confirm base64url decoding of attestationObject produces parseable CBOR before verification"],"exampleFix":"// before: hand-built attestation\nbody.response.attestationObject = btoa(JSON.stringify({fmt: 'android-key', attStmt: {alg: -7, x5c: [...]}}));\n// after: pass through the real object\nconst body = cred.toJSON(); // attestationObject untouched base64url CBOR","handlingStrategy":"validation","validationCode":"import base64, cbor2  # type: ignore\n\ndef android_key_attestation_wellformed(att_obj_b64: str) -> bool:\n    try:\n        att = cbor2.loads(base64.urlsafe_b64decode(att_obj_b64 + '=='))\n        stmt = att.get('attStmt', {})\n        return bool(stmt.get('sig')) and bool(stmt.get('alg')) and bool(stmt.get('x5c'))\n    except Exception:\n        return False","typeGuard":null,"tryCatchPattern":"try:\n    verify_android_key_format(...)\nexcept InvalidRegistrationResponse as e:\n    if 'missing signature (Android Key)' in str(e):\n        logger.warning('incomplete android-key attStmt received — client likely hand-built it')\n        return json_response({'error': 'invalid_attestation'}, 400)","preventionTips":["Forward response.attestationObject verbatim from cred.toJSON(); never rebuild attStmt client-side","Optional: skip attestation (attestation: 'none') at registration if you do not consume it — avoids this whole class","In tests, use virtual authenticators that emit spec-compliant attestation statements"],"tags":["webauthn","attestation","android-key","registration"],"backgroundTag":null,"analyzedSha":"1e661df964b1b264c9cef3ab28430d4785be3fda","analyzedAt":"2026-08-15T05:22:16.142Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}