Skip to content

Communicate that an attestation statement was fully chained to a trust anchor #802

Open

Description

@MasterKale

Describe the issue

Nothing in verifyRegistrationResponse() communicates the fact that a response may contain an attestation statement, but that the attestation statement wasn't actually confirmed to chain to a specified trust anchor. This would typically be because A) no trust anchors were specified for the attestation format (e.g. MDS isn't being used), or B) it's "packed" self attestation that doesn't verify anything but proof of possession of the new credential's private key.

Additionally, some attestation statements, like "android-key", "android-safetynet", and "apple" will always chain to a trust anchor because they have default trust anchors registered with SettingsService. Others, like "packed" and "tpm", won't actually be verified unless the RP explicitly defines trust anchors for them or opts into using FIDO MDS (and even then only when MDS contains trust anchors for the given AAGUID.)

Right now in all these cases responses containing attestations will return as "verified: true" even if the statement couldn't actually be verified. But if I add something like "registrationInfo.fmtVerified" to the output of verifyRegistrationResponse() then I could signal to RPs, "this response contained an attestation statement, and the statement was fully chained to a trust anchor."

Proposed Examples

"packed" attestation was verified to chain to a trust anchor:

const verified = await verifyRegistrationResponse({...});
console.log(verified.registrationInfo.fmt); // "packed"
console.log(verified.registrationInfo.fmtVerified); // "packed:x5c"

"packed" attestation contained self attestation (signed using the passkey private key):

const verified = await verifyRegistrationResponse({...});
console.log(verified.registrationInfo.fmt); // "packed"
console.log(verified.registrationInfo.fmtVerified); // "packed:self"

No trust anchors were specified so "tpm" attestation had a valid signature but x5c[0] used to verify the signature wasn't chained to a trust anchor:

const verified = await verifyRegistrationResponse({...});
console.log(verified.registrationInfo.fmt); // "tpm"
console.log(verified.registrationInfo.fmtVerified); // undefined

"android-key" attestation was verified to chain to a trust anchor:

const verified = await verifyRegistrationResponse({...});
console.log(verified.registrationInfo.fmt); // "android-key"
console.log(verified.registrationInfo.fmtVerified); // "android-key"

"none" attestation would I guess return "none" for both because it's technically true?

const verified = await verifyRegistrationResponse({...});
console.log(verified.registrationInfo.fmt); // "none"
console.log(verified.registrationInfo.fmtVerified); // "none"

Activity

  1. added this to the v14.1.0 milestone on Sep 7, 2026
  2. changed the title [-]Communicate that an attestation statement was fully verified[/-] [+]Communicate that an attestation statement was fully chained to a trust anchor[/+] on Sep 7, 2026
  3. modified the milestones: v14.1.0, v14.2.0 on Oct 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions