Summary
In version 5.3.0 of the Symfony bundle, Webauthn\Bundle\Policy\ClientOverridePolicy
defaulted to allowing all client overrides, including userVerification.
A client could send {"userVerification": "discouraged"} in the assertion
or attestation options request to override a server-configured
userVerification: required, causing the emitted WebAuthn options to
instruct the authenticator to skip user verification. The
CheckUserVerification ceremony step then read the same downgraded
options and skipped its check.
Affected versions
- Vulnerable: 5.3.0
- Patched: 5.3.1
5.3.0 was released on 2026-05-01 and 5.3.1 was published roughly
18 hours later, on 2026-05-02. Practical exposure window was minimal.
Note on earlier 5.x versions
Versions 5.0.0 to 5.2.x did not ship ClientOverridePolicy (introduced
in 5.3.0), so the exact code path described above does not apply.
However, on those versions the ProfileBasedRequestOptionsBuilder
and ProfileBasedCreationOptionsBuilder already passed the
client-supplied userVerification value directly to the options
factory, where the profile value is only applied via ??=. The
functional outcome (a client can downgrade userVerification) is the
same. The recommended mitigation (see below) applies regardless of
the version, and users on 5.0.x – 5.2.x are encouraged to upgrade to
5.3.1 or later.
Severity
This is a defense-in-depth issue rather than a primitive that grants
authentication on its own:
- The attacker must already possess the victim's authenticator (a stolen
security key, an unlocked device). Without that, the downgrade is
inconsequential.
- The framework exposes the actual UV outcome on the returned
authenticator data (AuthenticatorData::isUserVerified()).
Applications that gate sensitive operations on this flag — as
documented — remain protected even on the vulnerable version.
Mitigation
Applications gating sensitive operations on user verification MUST
re-check the UV flag on the returned authenticator data after a
successful ceremony, regardless of what was requested in the options:
if (! $authenticatorData->isUserVerified()) {
throw new AccessDeniedHttpException('User verification is required.');
}
This is the authoritative signal that user verification actually
occurred. The hardened default in 5.3.1 closes the implicit
profile-bypass; the application-level check remains the recommended
defense in depth and is now documented explicitly in the
User Verification
guide.
Fix
ClientOverridePolicy::canOverride() now defaults to false instead
of true. The Symfony bundle DI configuration ships
user_verification overrides as disabled by default, with a
default allowed_values list that excludes discouraged even when
an operator opts in.
Credit
Reported by @offset.
Summary
In version 5.3.0 of the Symfony bundle,
Webauthn\Bundle\Policy\ClientOverridePolicydefaulted to allowing all client overrides, including
userVerification.A client could send
{"userVerification": "discouraged"}in the assertionor attestation options request to override a server-configured
userVerification: required, causing the emitted WebAuthn options toinstruct the authenticator to skip user verification. The
CheckUserVerificationceremony step then read the same downgradedoptions and skipped its check.
Affected versions
5.3.0 was released on 2026-05-01 and 5.3.1 was published roughly
18 hours later, on 2026-05-02. Practical exposure window was minimal.
Note on earlier 5.x versions
Versions 5.0.0 to 5.2.x did not ship
ClientOverridePolicy(introducedin 5.3.0), so the exact code path described above does not apply.
However, on those versions the
ProfileBasedRequestOptionsBuilderand
ProfileBasedCreationOptionsBuilderalready passed theclient-supplied
userVerificationvalue directly to the optionsfactory, where the profile value is only applied via
??=. Thefunctional outcome (a client can downgrade
userVerification) is thesame. The recommended mitigation (see below) applies regardless of
the version, and users on 5.0.x – 5.2.x are encouraged to upgrade to
5.3.1 or later.
Severity
This is a defense-in-depth issue rather than a primitive that grants
authentication on its own:
security key, an unlocked device). Without that, the downgrade is
inconsequential.
authenticator data (
AuthenticatorData::isUserVerified()).Applications that gate sensitive operations on this flag — as
documented — remain protected even on the vulnerable version.
Mitigation
Applications gating sensitive operations on user verification MUST
re-check the
UVflag on the returned authenticator data after asuccessful ceremony, regardless of what was requested in the options:
This is the authoritative signal that user verification actually
occurred. The hardened default in 5.3.1 closes the implicit
profile-bypass; the application-level check remains the recommended
defense in depth and is now documented explicitly in the
User Verification
guide.
Fix
ClientOverridePolicy::canOverride()now defaults tofalseinsteadof
true. The Symfony bundle DI configuration shipsuser_verificationoverrides as disabled by default, with adefault
allowed_valueslist that excludesdiscouragedeven whenan operator opts in.
Credit
Reported by @offset.