fix: enforce WebAuthn assertion type and User-Present flag - #118
Open
alberto-crossmint wants to merge 1 commit into
Open
fix: enforce WebAuthn assertion type and User-Present flag#118alberto-crossmint wants to merge 1 commit into
alberto-crossmint wants to merge 1 commit into
Conversation
Two spec-mandated checks were missing from the WebAuthn verifier (W3C WebAuthn §6.1, §7.2.11): 1. clientDataJSON.type must be "webauthn.get" for an authentication assertion. Without this, a signature produced during a navigator.credentials.create() ceremony (type "webauthn.create") could be replayed against the smart account if its challenge happened to match a transaction hash. 2. The User-Present (UP) bit in authenticator_data flags must be set. Without this, the contract trusted whatever the authenticator reported, accepting assertions where the user never interacted. Both checks are cheap (string compare, single bit test) and run in the existing fail-fast block before the ECDSA verify. Out of scope: clientDataJSON.origin and authenticator_data rpIdHash enforcement. Both require storing per-signer expected values and amount to a WebauthnSigner schema change tracked separately.
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.
Summary
The WebAuthn verifier (
auth/signers/webauthn.rs) was missing two spec-mandated checks:clientDataJSON.type == "webauthn.get"tyfield toClientDataJsonand reject anything other than"webauthn.get"authenticator_dataflagsauthenticator_data[32] & 0x01 == 0Both checks are cheap (one string compare, one bit test) and live in the existing fail-fast block ahead of the ECDSA verification.
Why this matters
Type check: A signature produced during a
navigator.credentials.create()ceremony is signed over aclientDataJSONwhosetypeis"webauthn.create". Without the type check, that signature could be replayed against this contract if its challenge happened to match a Stellar transaction hash. The attacker scenario requires luring the victim into a registration ceremony on a hostile origin, but the defense is essentially free and removes a class of cross-ceremony replay risk that the WebAuthn spec specifically calls out.UP flag: Modern authenticators almost always set the UP bit, but the spec is clear that the verifier must require it — without enforcement the contract trusts whatever the authenticator reports, including assertions that occurred without any user interaction.
Test plan
test_webauthn_wrong_type_rejected— assertion withtype: "webauthn.create"returnsErr(InvalidWebauthnClientDataJson).test_webauthn_wrong_type_rejected_end_to_end— same, throughtry_invoke_contract_check_auth.test_webauthn_missing_user_present_flag_rejected—authenticator_data[32] = 0x00returnsErr(InvalidWebauthnClientDataJson).test_utils::WebauthnTestSigneralready producestype: "webauthn.get"andflags: 0x01so no regression.Out of scope
clientDataJSON.originandauthenticator_datarpIdHashenforcement. Both require a per-signer expected value (origin string / RP ID), which means aWebauthnSignerschema change and migration. Tracked for a future v3 schema bump.Backwards compatibility
Real-world authenticators producing
type: "webauthn.get"with UP set (overwhelming majority) are unaffected. Any client previously relying on the lax verification behavior — sending non-"webauthn.get"ceremonies or zero flags — will now be rejected. A grep across known integrations is suggested before rollout.