fix(conformance): load the metadata the tools ship, echo only requested extensions - #253
Merged
Merged
Conversation
…ed extensions The first real FIDO2 conformance runs surfaced three defects, all confined to FIDO_CONFORMANCE_MODE, which is refused under a production NODE_ENV. The tools' metadata archive unzips to a nested metadataStatements/ directory and the loader only read the top level, so it silently loaded nothing. With requireKnownAuthenticator set the metadata service runs strict, so every conformance authenticator was refused as unlisted and every registration failed. That cascaded into the tests which depend on a registration having succeeded, rather than showing up as a metadata failure. The directory is now read recursively, so the archive can be dropped in unedited as the docs already said. The tools sign their Apple, Android Key and SafetyNet statements with their own test roots, so validating those against the real vendor roots could never succeed. Those preset roots are now cleared in conformance mode, which lets the roots carried in the metadata statement apply instead. Android Key attestation verifies for the first time as a result. generateRegistrationOptions always appends its own credProps, and the tools compare the echoed extensions against the requested set for exact equality, so every options request carrying extensions failed. The requested set is now echoed verbatim over the library's answer. The authentication options path was already correct, since the library passes extensions through there unchanged. A conformance run now reports zero failures.
This was referenced Sep 3, 2026
Bccorb
added a commit
that referenced
this pull request
Sep 3, 2026
…ance statements (#254) Registration attestation was wired up in #168 and #169, but no test drove the individual statement formats. Hand-rolling one is close to reimplementing the authenticator, so these statements were captured from a FIDO2 conformance run and committed as fixtures. Packed, TPM and fido-u2f each verify end to end through the same call the WebAuthn controller makes, reporting the format and the model they came from. Each is then refused twice over, once with the attestation signature altered and once with the authenticator data altered. Android Key is covered alongside them because it proves the vendor root handling from #253: it is refused against the real Google roots and verifies once the preset roots are cleared, which is what conformance mode does. The metadata-absent path is covered in both requireKnownAuthenticator postures, offline. Passing no MDS servers and no statements makes the fixture's model unlisted by construction rather than by network luck, so strict refuses it and permissive registers it with no statement. Android SafetyNet is left as a todo with the reasoning recorded next to it. The conformance tools never emit one, and the verifier refuses any statement more than sixty seconds old, so a committed fixture could only pass against a faked clock. One thing worth stating, since it looks like a bug and is not: fido-u2f signs an explicit list of fields rather than the authenticator data as a whole, and the signature counter is not among them, so altering the counter verifies happily. The RP ID hash is altered instead. Co-authored-by: Brandon Corbett <Bccorb@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #172.
The FIDO2 conformance test tools were run against a local instance for the first
time. The first run reported 15 failures. This fixes the three defects behind
them, and a run now reports zero failures.
All three are confined to
FIDO_CONFORMANCE_MODE, which is refused under aproduction
NODE_ENV, so no deployed behaviour changes.Metadata statements were never loaded
The tools' "DOWNLOAD SERVER METADATA" archive unzips to a nested
metadataStatements/directory, and the loader only read JSON files at the toplevel of
FIDO_CONFORMANCE_METADATA_DIR. It silently found none.With
requireKnownAuthenticatorset, the metadata service runs in strict mode,so every conformance authenticator was refused as unlisted and every
registration failed. That cascaded into the tests which depend on a registration
having already succeeded, so the failures pointed away from the actual cause.
Confirmed directly against the library before and after:
The directory is now read recursively, so the archive can be dropped in unedited
as the documentation already promised.
Vendor attestation roots blocked their own tests
The tools sign their Apple, Android Key and SafetyNet statements with their own
test roots, so validating those against the real vendor roots could never
succeed. Those preset roots are now cleared in conformance mode, which lets the
roots carried in the metadata statement apply instead. Android Key attestation
verifies for the first time as a result.
Registration options advertised an extension nobody asked for
generateRegistrationOptionsalways appends its owncredProps, and the toolscompare the echoed extensions against the requested set for exact equality:
The requested set is now echoed verbatim over the library's answer. The
authentication options path was already correct, since the library passes
extensions through there unchanged.
Verification
Three conformance runs, 347 captured requests in the last one. Every options
call answered
ok, no ceremony was lost, and every remaining refusal is anegative test the tools intend to fail: corrupted attestation internals, bad
origins, unsupported formats.
Attestation formats verified end to end during a run: packed, tpm, fido-u2f,
android-key and none. Android SafetyNet is never exercised by the tools even
with every test group selected, which is worth confirming before closing #210.
Full suite green: 1219 passed, 1 skipped. Lint, typecheck, format and coverage
thresholds all clean.