Browse Source
`is_webauthn_2fa_supported()` was previously checked only at
`POST /two-factor/get-webauthn`. The three sibling 2FA WebAuthn HTTP
routes — `generate_webauthn_challenge`, `activate_webauthn` (and its
`PUT` alias), and `delete_webauthn` — are user-facing Bearer-authed
endpoints that any client can hit directly. A client that skips the
listing endpoint reached the unguarded `WEBAUTHN.start_passkey_registration`
/ `WEBAUTHN.finish_passkey_registration` calls.
Concretely: under a misconfigured `DOMAIN` (IP literal, hostless URL —
anything where `Url::domain()` returns `None`), the `WEBAUTHN` `LazyLock`
panics on first access from inside `WebauthnBuilder::new("", ..)`,
poisoning the lock so every subsequent WebAuthn touch in the process
panics too. The listing endpoint's gate avoids this on the legitimate
flow but leaves the same panic-cascade reachable via any direct call
to a sibling endpoint.
Apply the same guard at the two endpoints that access `WEBAUTHN`:
- `generate_webauthn_challenge` (calls `WEBAUTHN.start_passkey_registration`)
- `activate_webauthn` (calls `WEBAUTHN.finish_passkey_registration`;
also covers `activate_webauthn_put` which is a thin wrapper)
`delete_webauthn` doesn't touch `WEBAUTHN` (pure DB work over the
`TwoFactor` row), so it doesn't need the guard.
The check is a pure function of `CONFIG.domain()`; the response is
identical to the listing endpoint's, so well-configured deployments
see no behaviour change.
pull/7297/head
1 changed files with 8 additions and 0 deletions
Loading…
Reference in new issue