9d149ff313cfee6551259d37328823105eda2fb6 [M151] [FedCM] Fix UAF when double clicking user other account
The bug at a glance
A re-entrant use-after-free of the AccountsFetcher in the privileged browser process is reachable from ordinary web content that invokes a FedCM dialog, gated only by a double-click on ‘Use a different account’; browser-process UAFs are high severity even with user interaction.
A malicious or colluding IdP page can race the FedCM accounts fetch so that re-clicking ‘Use a different account’ re-registers the Request as a sign-in-status observer, triggering a synchronous callback that frees the object currently executing, giving an attacker a controllable UAF in the browser process.
Root cause
Request::LoginToIdP registered Request as an IdpSigninStatusObserver and opened the IdP login popup. Clicking ‘Use a different account’ a second time while the accounts fetch was still in flight re-registered Request as an observer; when the pending response arrived, UpdateIdpSigninStatusForAccountsEndpointResponse synchronously notified observers, so Request kicked off a new accounts fetch that deleted the current AccountsFetcher while it was still running inside OnAccountsResponseReceived. The fix skips re-registration when the login popup is already open and adds a WeakPtr guard so OnAccountsResponseReceived returns safely if the fetcher is destroyed during the synchronous status update.
Key code
WeakPtr guard across the synchronous sign-in-status update that can delete the fetcher
base::WeakPtr<AccountsFetcher> weak_this = weak_ptr_factory_.GetWeakPtr();
webid::UpdateIdpSigninStatusForAccountsEndpointResponse(
idp_config_url, status, idp_info->has_failing_idp_signin_status,
permission_delegate_);
if (!weak_this) {
return;
}
Patch walkthrough
content/browser/webid/accounts_fetcher.cc— Captures a WeakPtr before UpdateIdpSigninStatusForAccountsEndpointResponse (which synchronously notifies observers and can delete the AccountsFetcher) and bails out if the object was destroyed, preventing the use-after-free on the rest of OnAccountsResponseReceived.content/browser/webid/request.cc— When LoginToIdP runs while dialog_type_ is already kLoginToIdpPopup it now re-shows (refocuses) the modal and returns early instead of calling AddIdpSigninStatusObserver again, removing the duplicate observer registration that created the re-entrant fetch; also reworks the DialogType UMA/devtools-close logic to only fire on an actual dialog-type change.content/browser/webid/request_unittest.cc— Adds a regression test asserting that a second LoginToIdP while the popup is open refocuses without re-registering the observer (AddIdpSigninStatusObserver called exactly once) and preserves query parameters.
Background
FedCM — Federated Credential Management is a browser API that mediates federated sign-in between a relying party and an identity provider (IdP) via browser-drawn account-chooser dialogs.
IdpSigninStatusObserver — Observer interface notified when an IdP’s stored sign-in status changes, used to re-fetch accounts after the user logs into the IdP popup.
AccountsFetcher — Browser-side helper that fetches the IdP accounts endpoint and reports results via OnAccountsResponseReceived.
Vulnerability window
- Reachability — Reachable from ordinary web content in a stock build: a page using the FedCM API displays the account chooser and the user clicks ‘Use a different account’.
- Trigger — The user refocuses the dialog and double-clicks ‘Use a different account’ again while the accounts fetch is still in flight, re-registering Request as an observer.
- Primitive — The arriving accounts response synchronously updates sign-in status, which notifies the re-registered observer and starts a new fetch that frees the AccountsFetcher mid-callback, yielding a use-after-free in the browser process.
- Escalation — Shaping the freed AccountsFetcher allocation could turn the UAF into read/write of attacker-influenced memory in the browser process (inferred).
Proof of concept
Conceptually: an IdP/relying-party page invokes FedCM, the account chooser is shown, the user clicks ‘Use a different account’ to open the login popup, then clicks it again before the queued accounts fetch completes; the second click re-arms the observer so the completing fetch re-enters and destroys the live fetcher. No working exploit is provided.
Exploitation
- Setup — Serve a FedCM-enabled relying party plus an IdP whose accounts endpoint response can be delayed to widen the race window (inferred).
- Trigger — Induce the double-click on ‘Use a different account’ (social engineering or scripted focus/timing) so the second LoginToIdP re-registers the observer.
- Groom — Reclaim the freed AccountsFetcher with controlled data before the dangling use completes (inferred).
Detection & hunting
For defenders and detection engineers:
- weggli: observer re-registration without an already-open/already-registered guard (e.g. AddIdpSigninStatusObserver called in a path that can run twice) — Audit FedCM Request paths that register observers for idempotency when the popup/dialog is already open.
- grep for synchronous observer-notification calls (UpdateIdpSigninStatus) not followed by a WeakPtr/this-liveness check* — Flag methods that call synchronous notifiers and then keep touching member state without re-validating the object.
Audit directions
- content/browser/webid/ — Review every synchronous callback that can re-enter and delete AccountsFetcher/Request (OnAccountsResponseReceived and siblings) for missing WeakPtr guards.
- Observer-registration sites across FedCM — Look for user-repeatable actions (dialog buttons) that register observers without checking existing state, enabling duplicate registration and re-entrancy.