In 2022, Microsoft Research published “Pre-hijacking Attacks on Web User Accounts” at USENIX Security. It surveyed 75 popular services and found that roughly 47% were vulnerable to one or more variants of account pre-hijacking, a class of attack that lets an adversary gain persistent access to an account the victim hasn’t created yet.

The paper is excellent. But the way the industry absorbed it has created a new problem: the two main variants get lumped together under the same label, triaged as if they’re the same threat, and dismissed or accepted for the wrong reasons.

I independently identified and reported an instance of this class to Bugcrowd in 2021, before Microsoft Research submitted or published their paper, against a major productivity platform. It was marked Not Applicable. The triager had conflated the two variants, assumed a higher precondition than was actually required, and closed it as low-impact. The report was publicly disclosed in March 2022: Bugcrowd disclosure FF0E1B7E.

This article is the explanation I wish I’d been able to link to at the time.


The uncomfortable truth about “Sign in with X”

SSO is marketed as a security feature. One strong identity provider, fewer passwords, centralised revocation. In theory, that is correct.

But many services implement SSO in a way that silently inverts this: instead of the user choosing to link an SSO provider to their account, the service automatically links any SSO provider that presents a matching email address. No prompt. No verification that the user set up that provider. No notification that the link was created.

The consequence is severe. Every SSO provider a service configures gains implicit full access to every account on that platform, regardless of whether the account holder ever signed up with that provider, ever used it, or even knows it exists.

If an enterprise customer has 500 employees on @company.com using a service that trusts five SSO providers, and none of those employees have ever used anything other than email and password: all 500 accounts are silently accessible via all five providers. The employees never consented to this. The enterprise likely does not know. And if any of those five providers suffers a breach, a credential leak, or an insider threat, the blast radius includes every account on every service that blindly trusts them.

This is not a theoretical concern. Major identity providers have been targets of sophisticated attacks. An OAuth token forgery or a compromised Workspace admin is not science fiction; it has happened. The question is not “could an IdP get hacked” but “if it does, how many services are exposed by design.”

SSO configured without a consent gate does not improve your security posture. It adds an undisclosed attack surface to every account on the platform.


The two variants

Variant 1: True Pre-Hijacking

The attacker acts before the victim has an account.

  1. Attacker registers an account at target.com using victim@example.com as the email address.
  2. The registration succeeds but the account is unverified: the attacker never clicks the confirmation email.
  3. Victim later discovers target.com and signs up via any SSO option (Google, Apple, Microsoft, etc.) using their real victim@example.com identity.
  4. The service processes the OAuth callback and uses it to verify the pre-existing unverified account, the one the attacker registered.
  5. Attacker’s original password still works. Both parties now have access to the same account.

Precondition: knowing the victim’s email address, and the victim not having registered yet.

No access to the victim’s accounts at any identity provider. No phishing. No privileged infrastructure access. The attacker only needs an email address (something that’s often public, easily guessable, or obtainable from a data breach) and to get there first.

This is the severe variant. The precondition is trivially achievable, the victim’s own action triggers the takeover, and it leaves no trace the victim can detect.

There is also a compounding risk: the more SSO providers a service adds, the more paths the victim can use to unknowingly activate the attacker’s account. Every new “Sign in with X” button is another trigger.


Variant 2: Classic-Federated Merge

The attacker acts after the victim already has a verified account.

  1. Victim registers at target.com with victim@example.com + a password, completes email verification.
  2. Later, the victim signs in via an SSO option using the same address.
  3. The service silently merges the two identities, with no ownership re-check, no consent prompt, no notification email.
  4. An attacker who can obtain an OAuth token from that provider asserting ownership of victim@example.com can now sign into the victim’s account.

Precondition: the ability to issue or forge an OAuth token for the victim’s email address at any SSO provider the service trusts.

This means a Workspace admin for the victim’s domain at any configured provider, an infrastructure actor at one of those providers, or a token forgery vulnerability in any of them. High bar per provider, but that bar only needs to be cleared once, for any one of the configured providers.

Here is the critical point: every additional SSO provider a service configures is another permanent trust delegation on every account on the platform. A service trusting Google, Apple, Microsoft, and Slack is not four separate security choices that users can opt into. It is a platform-wide decision that all four providers can access any account. The attacker targets whichever of those four has the weakest controls or the most accessible admin path for the victim’s domain.

The design flaw is also cumulative. Every time a product team adds a new “Sign in with X” button to improve conversion, they silently expand the attack surface for every existing account, including accounts belonging to users who will never use that provider.


Why the confusion matters

These two variants are almost always discussed as if they’re the same. They aren’t. The table below shows why they require different remediation and deserve different severity ratings:

True Pre-Hijacking Classic-Federated Merge
When Before victim registers After victim has verified account
Precondition Victim’s email + victim not yet registered OAuth access at any trusted provider for victim’s domain
Severity High (P2/P3) Medium (P3/P4)
Victim action required Yes (victim triggers it) No
Detectable by victim No No
Scales with more SSO providers Yes, more triggers Yes, more attack paths
Remediation Invalidate unverified accounts on federated merge Require explicit consent before linking

The typical triage mistake: a researcher submits Variant 1, the triager reads it as Variant 2, assumes “requires a provider account to be compromised”, and closes as informational. The researcher gets an N/A on a finding that had a trivially-exploitable precondition.


A real-world example: Atlassian’s multi-IdP trust

The finding I reported in 2021 was a variant of this class against Atlassian’s product suite. The specific behaviour: Atlassian trusted any of their configured SSO providers (Google, Apple, Microsoft, Slack) to silently merge into an existing verified account sharing the same email.

An enterprise running Atlassian on @company.com with no Google relationship, no Apple devices, and no Slack contract; their employees’ accounts were silently reachable via any of those providers. The employees never chose this. The enterprise was not informed. And each time Atlassian added a new SSO option, the implicit trust was extended to every existing account on every Atlassian instance.

The report was marked Not Applicable. In retrospect, the triage response considered each provider in isolation and concluded the precondition was high. It did not account for the compounding effect: the relevant question is not “can the attacker compromise Google” but “can the attacker compromise any one of the N providers Atlassian trusts” - and that bar lowers every time the product ships a new “Sign in with” option.

The finding is publicly disclosed: Bugcrowd disclosure FF0E1B7E, reported in 2021, publicly disclosed March 2022, roughly a year before Microsoft Research’s paper reached the security community.


The blast radius of a single IdP breach

This is worth stating plainly.

When a service silently merges accounts on OAuth callback, it is not just exposing its own users. It is contributing to a class of systemic risk. If a major identity provider’s token issuance is compromised, every service in this category becomes a lateral movement target in the same incident.

A security team responding to an IdP breach would need to audit every service their organisation uses and ask: does this service require re-authentication or explicit consent before linking? If not, every account on that service should be treated as potentially accessible to the attacker for the duration of the breach window, even if the user of that account never used that IdP.

Services that implement proper consent gates are isolated from this blast radius. Services that silently trust OAuth assertions are not.


Beyond the technical risk, both variants create a compliance problem that most affected platforms have not acknowledged.

The user was never told

In almost every jurisdiction with data protection law, users have a right to know who can access their data and under what conditions. GDPR Article 13/14 requires controllers to disclose recipients of personal data. Article 28 requires that sub-processors be named in Data Processing Agreements. CCPA requires disclosure of third parties data is shared with.

Both variants create undisclosed access paths. In Variant 2, SSO providers can silently merge into existing accounts and access their data. In Variant 1, SSO providers are used to verify and activate accounts without the account holder ever being told that an SSO provider was the deciding authority on who owns that account. In neither case did the user consent to that trust relationship, and in neither case is it typically disclosed.

A platform that silently trusts SSO providers in either way has created data access paths that are almost certainly absent from its privacy policy, its sub-processor list, and the DPA it signs with enterprise customers. The SSO providers were added as a login convenience feature, not as data processors, and the legal documentation was never updated to reflect the authority they implicitly hold.

This is not a minor technicality. If a user or enterprise customer asks “who can access my data on this platform”, the honest answer includes every SSO provider configured, because a compromised or malicious actor at any of those providers can either activate attacker-controlled accounts (Variant 1) or directly access existing accounts (Variant 2). If that answer is not in the privacy policy, the platform is likely in breach of disclosure obligations.

The competitor scenario

Consider a real scenario that is not theoretical: a platform used by competing enterprises which also offers “Sign in with” options from multiple tech giants.

If that platform silently trusts Google, Apple, and Microsoft OAuth assertions, then in principle a Google employee with appropriate infrastructure access could merge into an account belonging to a Microsoft or Amazon employee on that platform. The account might contain customer conversations, sales pipeline data, product roadmap discussions, or support tickets involving confidential business information.

The platform’s terms of service almost certainly promise not to share customer data with third parties without consent. The DPA signed with those enterprise customers almost certainly enumerates who has access. Google, Apple, and Microsoft are not on that list.

This is not hypothetical paranoia. Large enterprise security teams explicitly audit which third parties can access their data before approving a SaaS vendor. If the answer includes every SSO provider the platform has ever added, and that answer is buried in an obscure authentication design decision rather than disclosed in the security documentation, the vendor is misrepresenting their data access controls to their customers.

The liability question

A platform that is breached via a compromised SSO provider will face a difficult position: explaining to affected customers that the access vector was an authentication feature the platform added, that no individual user set up, that was never disclosed as a data access path, and that the customer had no way to disable.

That is a combination that regulators and litigants find compelling. GDPR fines for Article 28 violations (undisclosed sub-processors) reach 2% of global annual turnover. Class actions in CCPA jurisdictions have lower individual thresholds. Enterprise customers with contractual data access controls may have direct breach of contract claims.

Technically, there is a non-technical solution: update the privacy policy, sub-processor list, and DPA templates to explicitly disclose that every configured SSO provider holds implicit access to every account on the platform. No code changes required.

Most companies will not do this. The reason is straightforward: any enterprise customer reading that disclosure would immediately raise questions in their security review. “You are telling us that Google, Apple, Microsoft, and Slack can all access our employees’ accounts on your platform, without those employees ever using those providers?” That is a difficult conversation to have during a sales cycle, and a harder one to have after a contract is signed.

The reluctance to disclose is itself informative. If the access path is too embarrassing to put in the DPA, it is too risky to leave in the product. The non-technical fix and the technical fix have the same outcome: platforms that implement proper consent gates can honestly say that SSO providers only have access to accounts where the user explicitly linked them. That is a disclosable, defensible position. Silent trust across all accounts is neither.

The fix is the same as the technical fix: a proper consent gate means the SSO provider is only involved when the user explicitly opted in. A user who never linked a provider to their account cannot have that account activated by an attacker via that provider (Variant 1), and cannot have it silently accessed via that provider (Variant 2). The legal liability mirrors the technical attack surface exactly.


Remediation

Both variants share a common fix at the merge step.

Require explicit, authenticated consent before linking a federated identity to an existing account.

Concretely:

“An account with this email already exists. Enter your current password to link this sign-in method to it.”

This single gate eliminates True Pre-Hijacking entirely (attacker can’t supply the password) and limits Classic-Federated Merge to attackers who can obtain both the OAuth token and the existing password, a dramatically higher bar.

Additionally:

  • Send a notification email whenever a new sign-in method is added to an account.
  • Expose a “linked sign-in methods” page in account settings, with the ability to remove links.
  • Treat an unverified pre-existing account as a new account when a federated login arrives for the same email: do not merge.
  • Audit every SSO provider configured on the platform. Each one is a permanent trust delegation on every account. Adding providers should require a security review, not just a product decision.

Auth0’s model is the reference implementation: federated sign-in always creates a separate account by default, and explicit account linking requires the user to be authenticated to both simultaneously.


Reproducing both variants

The best way to understand the difference is to see it. I built a minimal self-contained demo: a Node.js service with a fake SSO button (no real OAuth, just a simulated IdP assertion) that demonstrates both vulnerable variants and the fixed behaviour side-by-side.

No real credentials, no real OAuth. Each session is isolated per visitor.


References

  • Sudhodanan & Paverd, “Pre-hijacking Attacks on Web User Accounts”, USENIX Security 2022: usenix.org
  • My Atlassian/Slack disclosure, reported 2021, publicly disclosed March 2022: bugcrowd.com/disclosures/ff0e1b7e
  • CWE-287: Improper Authentication
  • CWE-1390: Weak Authentication