# Unverified email change and merge takeover

Identity fields set without ownership proof, then trusted by merge, invite or SSO flows

_Area: Web authentication and account takeover. Seen in 3 disclosed reports; one confirmed bounty: $5,000; latest 2021-01-07. Updated 2026-11-07._

## How it works

An account's email is treated as proof of identity, but some path sets or accepts that email without proving the user controls it. The broken assumption is that "the email on the account is verified." Once an unverified address sits on an account, downstream flows (account merge, invitation acceptance, SSO) read it as trusted and hand over control. The root cause is a missing ownership check at the point the email is written or accepted, combined with a downstream flow that never re-checks.

## Where it shows up

- Secondary or admin endpoints (staff, POS, sub-admins) that mutate email/name and skip the confirmation the main UI enforces [E1](https://bugbountylibrary.com/r/h1%3A867513.md)
- Account merge or "link your ID" flows that trust an already-set email as verified [E1](https://bugbountylibrary.com/r/h1%3A867513.md)
- Invitation acceptance that renders and accepts a pending invite for an unverified account [E2](https://bugbountylibrary.com/r/blog%3Aabss-me-posts-github-org-takeover.md)
- Email-change flows where the confirmation message is keyed to the old/stale address rather than the new one [E3](https://bugbountylibrary.com/r/h1%3A791775.md)
- SSO or master-password reset that keys off the account email [E3](https://bugbountylibrary.com/r/h1%3A791775.md)

## How to review

Find every write to an email/identity field and confirm each requires proof of control of the *new* address before it is stored as verified. Then check every consumer (merge, invite, SSO, reset) re-validates ownership rather than trusting the stored flag. The invariant: an email is only "verified" after a token sent to that exact address is returned; no flow may treat an unverified email as owned. For email change, confirm the verification message goes to the new address, not the old one [E3](https://bugbountylibrary.com/r/h1%3A791775.md). For invites, confirm acceptance is server-side gated on the invitee's verified email [E2](https://bugbountylibrary.com/r/blog%3Aabss-me-posts-github-org-takeover.md).

## How finders spotted it

- Noticed the POS Staff save request accepted an arbitrary email with no confirmation, and the Shopify ID merge prompt did not re-validate it; combined with a dev store whose email was self-verified [E1](https://bugbountylibrary.com/r/h1%3A867513.md)
- Probing org invite flows, created an account with the invitee's email and saw the invitation still rendered and was acceptable without verification, suspecting a client-side-only check [E2](https://bugbountylibrary.com/r/blog%3Aabss-me-posts-github-org-takeover.md)
- Saw the email-change confirmation went to the old address, hypothesized the system tracked the stale email, changed to an address they didn't control, then checked the victim store's owner email to confirm [E3](https://bugbountylibrary.com/r/h1%3A791775.md)

## Variants seen

- Unverified email set via secondary admin GraphQL endpoint, then trusted by merge flow [E1](https://bugbountylibrary.com/r/h1%3A867513.md)
- Unverified account claims a pending owner invitation [E2](https://bugbountylibrary.com/r/blog%3Aabss-me-posts-github-org-takeover.md)
- Confirmation link mailed to stale/attacker address, enabling claim of any email [E3](https://bugbountylibrary.com/r/h1%3A791775.md)

## Impact and severity

Full account and organization takeover. E1 took over accounts lacking a Shopify ID and swapped staff identity data [E1](https://bugbountylibrary.com/r/h1%3A867513.md). E2 seized an entire GitHub organization [E2](https://bugbountylibrary.com/r/blog%3Aabss-me-posts-github-org-takeover.md). E3 escalated from one account to every store sharing the victim email via SSO [E3](https://bugbountylibrary.com/r/h1%3A791775.md). Impact rose when the unverified email was chained into merge, invite or SSO flows that scaled reach beyond a single account.

## Evidence
- E1: https://bugbountylibrary.com/r/h1%3A867513.md
- E2: https://bugbountylibrary.com/r/blog%3Aabss-me-posts-github-org-takeover.md
- E3: https://bugbountylibrary.com/r/h1%3A791775.md
