# Email normalization and truncation mismatch

Validation, storage and lookup see different versions of the same email string

_Area: Web authentication and account takeover. Seen in 5 disclosed reports; 2 confirmed bounties: $500 and $1,000; latest 2025-07-17. Updated 2026-10-23._

## How it works
A security decision (domain allowlist, account uniqueness, SSO enforcement, reset delivery) is made on one version of an email string, but a different version is stored, looked up, or mailed. The gap between those versions is the bug. Fixed-width columns cut the string, a charset drops characters above a code point limit, control characters survive one step but not another, or a provisioning sync treats email as an independent mutable attribute. The check passes on the full string; the stored or delivered value is something else.

## Where it shows up
- Email stored in a fixed-width column (e.g. VARCHAR(128)) with no length validation before the allowlist check [E3](https://bugbountylibrary.com/r/h1%3A2224.md)
- MySQL `utf8` (not `utf8mb4`) columns silently cutting at the first code point >0xFFFF [E5](https://bugbountylibrary.com/r/h1%3A2233.md)
- Domain/SSO enforcement compared against a raw string without stripping trailing control characters or whitespace [E4](https://bugbountylibrary.com/r/h1%3A2101076.md)
- Login matching that is case-sensitive while normalization elsewhere collides variants; `email_verified` not enforced at login [E2](https://bugbountylibrary.com/r/h1%3A1342088.md)
- Provisioning that treats email as mutable without validating it against the immutable identity [E1](https://bugbountylibrary.com/r/h1%3A3178999.md)

## How to review
Trace the exact string from input through validation to storage to lookup to mail. The invariant: the value the allowlist/uniqueness/SSO check sees must be byte-identical to the value stored and later compared. Check column length and charset against the maximum possible input; confirm case-folding and Unicode normalization (NFC/NFKC) are applied identically at registration and login; confirm control characters are stripped before comparison. Test boundary lengths, astral-plane characters, case variants, and trailing control characters, then re-test login and reset. For provisioning (E1), the invariant differs: a mutable attribute like email must be validated against the immutable identity (username) before it can overwrite an account.

## Variants seen
- Length truncation dropping the appended allowed-domain suffix [E3](https://bugbountylibrary.com/r/h1%3A2224.md)
- Charset truncation at code points >0xFFFF [E5](https://bugbountylibrary.com/r/h1%3A2233.md)
- Case-variant unverified email colliding with the victim account [E2](https://bugbountylibrary.com/r/h1%3A1342088.md)
- Trailing control characters defeating SSO domain enforcement [E4](https://bugbountylibrary.com/r/h1%3A2101076.md)
- Mutable email attribute overwriting a victim's identity in SCIM sync [E1](https://bugbountylibrary.com/r/h1%3A3178999.md)

## Why fixes fail
E5 shows a second truncation vector left open after the length fix in E3; patching one truncation layer does not close others (charset, control characters, Unicode normalization).

## Impact and severity
Registration allowlist and SSO enforcement bypass, account shadowing, and full account takeover via reset or login [E1](https://bugbountylibrary.com/r/h1%3A3178999.md)[E2](https://bugbountylibrary.com/r/h1%3A1342088.md)[E3](https://bugbountylibrary.com/r/h1%3A2224.md)[E4](https://bugbountylibrary.com/r/h1%3A2101076.md). Severity rises when the mismatch yields full account control rather than mere registration.

## Evidence
- E1: https://bugbountylibrary.com/r/h1%3A3178999.md
- E2: https://bugbountylibrary.com/r/h1%3A1342088.md
- E3: https://bugbountylibrary.com/r/h1%3A2224.md
- E4: https://bugbountylibrary.com/r/h1%3A2101076.md
- E5: https://bugbountylibrary.com/r/h1%3A2233.md
