{"id":"GHSA-h4fw-6r7f-w494","aliases":[],"status":"published","title":"Webauthn has a User Verification Downgrade via Default-Open ClientOverridePolicy","description":"## Summary\n\nIn 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.\n\n## Affected versions\n\n- **Vulnerable**: 5.3.0\n- **Patched**: 5.3.1\n\n5.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.\n\n## Note on earlier 5.x versions\n\nVersions 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.\n\n## Severity\n\nThis is a **defense-in-depth** issue rather than a primitive that grants authentication on its own:\n\n- The attacker must already possess the victim's authenticator (a stolen security key, an unlocked device). Without that, the downgrade is inconsequential.\n- 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.\n\n## Mitigation\n\nApplications gating sensitive operations on user verification MUST re-check the `UV` flag on the returned authenticator data after a\nsuccessful ceremony, regardless of what was requested in the options:\n\n```php\nif (! $authenticatorData-\u003eisUserVerified()) {\n    throw new AccessDeniedHttpException('User verification is required.');\n}\n```\n\nThis 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\n[User Verification](https://webauthn-doc.spomky-labs.com/webauthn-in-a-nutshell/user-verification#checking-the-uv-flag) guide.\n\n## Fix\n\n`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.\n\n## Credit\n\nReported by @offset.","severity":{"version":"3.1","score":2.1,"vector":"CVSS:3.1/AV:P/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:N","level":"low","from":"ghsa"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-863"],"published":"2026-05-07T21:05:33Z","modified":"2026-05-07T21:18:48Z","fixes":[{"ecosystem":"Packagist","package":"web-auth/webauthn-framework","fixed_in":["5.3.1"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"Packagist","package":"web-auth/webauthn-framework","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"5.3.0"},{"fixed":"5.3.1"}]}]},{"source":"osv","ecosystem":"Packagist","package":"web-auth/webauthn-framework","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"5.3.0"},{"fixed":"5.3.1"}]}],"versions":["5.3.0"]}],"references":[{"url":"https://github.com/web-auth/webauthn-framework/security/advisories/GHSA-h4fw-6r7f-w494","tags":["web"]},{"url":"https://github.com/advisories/GHSA-h4fw-6r7f-w494"},{"url":"https://github.com/web-auth/webauthn-framework","tags":["package"]}],"sources":{"ghsa":[{"id":"GHSA-h4fw-6r7f-w494","title":"Webauthn has a User Verification Downgrade via Default-Open ClientOverridePolicy","description":"## Summary\n\nIn 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.\n\n## Affected versions\n\n- **Vulnerable**: 5.3.0\n- **Patched**: 5.3.1\n\n5.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.\n\n## Note on earlier 5.x versions\n\nVersions 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.\n\n## Severity\n\nThis is a **defense-in-depth** issue rather than a primitive that grants authentication on its own:\n\n- The attacker must already possess the victim's authenticator (a stolen security key, an unlocked device). Without that, the downgrade is inconsequential.\n- 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.\n\n## Mitigation\n\nApplications gating sensitive operations on user verification MUST re-check the `UV` flag on the returned authenticator data after a\nsuccessful ceremony, regardless of what was requested in the options:\n\n```php\nif (! $authenticatorData-\u003eisUserVerified()) {\n    throw new AccessDeniedHttpException('User verification is required.');\n}\n```\n\nThis 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\n[User Verification](https://webauthn-doc.spomky-labs.com/webauthn-in-a-nutshell/user-verification#checking-the-uv-flag) guide.\n\n## Fix\n\n`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.\n\n## Credit\n\nReported by @offset.","status":"published","published":"2026-05-07T21:05:33Z","modified":"2026-05-07T21:05:34Z","cvss":[{"version":"3.1","score":2.1,"vector":"CVSS:3.1/AV:P/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:N","level":"low"}],"cwes":["CWE-863"],"updated_at":"2026-11-02T14:40:03.762927Z"}],"osv":[{"id":"GHSA-h4fw-6r7f-w494","title":"Webauthn has a User Verification Downgrade via Default-Open ClientOverridePolicy","description":"## Summary\n\nIn 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.\n\n## Affected versions\n\n- **Vulnerable**: 5.3.0\n- **Patched**: 5.3.1\n\n5.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.\n\n## Note on earlier 5.x versions\n\nVersions 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.\n\n## Severity\n\nThis is a **defense-in-depth** issue rather than a primitive that grants authentication on its own:\n\n- The attacker must already possess the victim's authenticator (a stolen security key, an unlocked device). Without that, the downgrade is inconsequential.\n- 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.\n\n## Mitigation\n\nApplications gating sensitive operations on user verification MUST re-check the `UV` flag on the returned authenticator data after a\nsuccessful ceremony, regardless of what was requested in the options:\n\n```php\nif (! $authenticatorData-\u003eisUserVerified()) {\n    throw new AccessDeniedHttpException('User verification is required.');\n}\n```\n\nThis 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\n[User Verification](https://webauthn-doc.spomky-labs.com/webauthn-in-a-nutshell/user-verification#checking-the-uv-flag) guide.\n\n## Fix\n\n`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.\n\n## Credit\n\nReported by @offset.","status":"published","published":"2026-05-07T21:05:33Z","modified":"2026-05-07T21:18:48.987495Z","cvss":[{"version":"3.1","score":2.1,"vector":"CVSS:3.1/AV:P/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:N","level":"low"}],"cwes":["CWE-863"],"updated_at":"2026-11-02T15:46:48.546324Z"}]}}
