The attack in one paragraph
Attacker stands up a lookalike domain in front of login.yahoo.com (or login.aol.com, same backend). Cloudflare orange-cloud in front of a $5 VPS, valid TLS via the CF cert. The proxy serves the victim what looks pixel-for-pixel like the real Yahoo sign-in. Victim types their email and password. If MFA is enrolled, the victim gets a real Yahoo OTP, types it into the proxy, the proxy relays it. Yahoo issues the session cookies (Y, T, PH, F, plus a few secondaries). The proxy captures them on the way out and forwards the victim to their real Yahoo Mail inbox. Everything looks fine to the victim. The attacker pastes the captured cookies into a browser extension and is logged in as the victim.

Same shape as Microsoft 365 AiTM. Different details.
What you actually capture
Successful AiTM against login.yahoo.com produces these cookies, all on .yahoo.com:
| Cookie | httpOnly | secure | Lifetime | Notes | |---|---|---|---|---| | Y | false | true | ~1 year | Primary identity. JavaScript-accessible (XSS-readable). | | T | true | true | ~1 year | Session token. Properly scoped. | | PH | false | false | ~1 year | "Stay signed in" persistent hash. JavaScript-readable AND clear-text on HTTP. | | F | true | false | ~1 year | Flag cookie. Clear-text on HTTP. | | A1 / A1S / A3 | mixed | true | ~1 year | Secondary identity tiers. | | AS | true | true | browser session | Auth state on the login subdomain. |
Two things are worth calling out.
PH and F are secure=false. Anyone on the same network as the victim, who can downgrade or sniff a single HTTP request to a Yahoo property, can read those cookies. That's not AiTM, that's a coffee-shop attack from 2010. Yahoo still ships those cookies in 2026. We have no idea why.
Cookie lifetime is roughly one year. A successful AiTM capture buys an attacker up to a year of inbox access if nothing in your detection chain fires. Microsoft 365's tokens are much shorter-lived and CAE can revoke them within minutes of a risk signal. Yahoo has no equivalent revocation channel that we could observe from the captured session.
The cross-property blast radius
Yahoo identity is .yahoo.com-scoped. A successful capture against login.yahoo.com authenticates against:
- Yahoo Mail
- Yahoo News, Finance, Sports, Fantasy
- Flickr
- Anywhere else
.yahoo.comcookies are honored
It does NOT bridge to AOL Mail. AOL is on the same identity backend but enforces a separate auth domain (mail.aol.com). To compromise AOL Mail, the attacker needs a separate capture against login.aol.com.
If your user signs in through login.aol.com, you have AOL cookies, not Yahoo. Some flows do bridge Yahoo to AOL via SSO, but Yahoo cookies alone won't get you into AOL Mail.
Treat AOL and Yahoo as separate compromises even when the user thinks "they're the same login." They share the same Verizon-era backend, but they're separately fenced.

The AOL password step is worth a look on its own, because AOL bundles a Norton 360 / LifeLock cross-sell directly into the auth flow. Useful for defenders to know what the legitimate flow looks like when comparing to a suspected phish page.

Finding 1: the replay vector everyone writes about doesn't work
If you read most public AiTM writeups, the cookie-replay step is described as "paste this JavaScript into the browser console":
document.cookie = "Y=...; domain=.yahoo.com; path=/";chr(10)document.cookie = "T=...; domain=.yahoo.com; path=/";chr(10)// ...For Yahoo, this does not work. The critical session cookies (T, A1, A3, AS) are httpOnly, and document.cookie cannot set httpOnly cookies. The result is a half-loaded session, Yahoo issues a re-auth prompt, the attack fails.
The vector that actually works is a browser extension. Cookie-Editor accepts a JSON array describing each cookie with all its attributes, and writes them via chrome.cookies.set under the extension API. That API bypasses the httpOnly restriction (httpOnly is a JS-context protection, not an extension-context protection).
[chr(10){"name": "Y", "value": "...", "domain": ".yahoo.com", "path": "/",chr(10)"secure": true, "httpOnly": false, "sameSite": "lax",chr(10)"expirationDate": 1779843200, "storeId": null},chr(10){"name": "T", "value": "...", "domain": ".yahoo.com", "path": "/",chr(10)"secure": true, "httpOnly": true, "sameSite": "lax",chr(10)"expirationDate": 1779843200, "storeId": null}chr(10)]Why this matters for defenders: detection rules looking for document.cookie = patterns in browser process telemetry, or session-replay JS injection markers, miss the actual attack. The cookies arrive through the extension API with no JS trace in the browser session.
The detection has to be server-side: the cookies appear in a request without a corresponding interactive sign-in event in Yahoo's auth log. The timestamp mismatch is the tell.
Finding 2: Yahoo silently runs step-up authentication
This was the big surprise.
With captured Y + T + PH cookies replayed into a clean browser, you can do all of this with no further authentication:
- Read inbox, sent, drafts, spam, trash
- Read individual messages, including attachments
- Search the mailbox
- Read contacts (
contacts.yahoo.com) - Compose and send mail from the victim's address (no challenge)
But you cannot do any of this without re-authenticating:
- Open Yahoo Mail Settings (password prompt)
- Create or modify a filter / forwarding rule (password prompt)
- Change the account password (password + MFA)
- Change recovery email or phone (password + MFA)
- Grant OAuth app access (password + MFA)
- View or revoke active sessions (password prompt)
Yahoo doesn't document this. It surfaced during live testing.
What it means: a captured Yahoo session is a read token, not a configuration token. The attacker has the mailbox contents and an outbound-mail capability, but cannot easily install durable persistence (forwarding rules, OAuth grants, recovery-info pivot) without triggering another sign-in event at login.yahoo.com where the risk engine evaluates fresh and may challenge with MFA.
Two implications for defenders:
Treat Yahoo captures as data-exfiltration incidents first, ATO incidents second. The mailbox contents and contact graph are the certain loss. Configuration persistence is uncertain and detectable, look for re-auth attempts in the sign-in log within minutes of the original capture.
A step-up re-auth prompt the user did not initiate is a high-confidence indicator that an attacker with valid session cookies is trying to escalate. If a user reports "Yahoo asked me for my password while I was just sitting there," treat it as an active intrusion, not a UX glitch.
The gap in step-up auth is outbound message composition. Sending mail from the victim's account is not gated. So the attacker can pivot to BEC against the victim's contacts using the legitimate account, with no challenge, until the user notices.
Finding 3: Yahoo's RSC streaming defense doesn't survive a CDN
Yahoo's login page is served differently to different User-Agents:
| UA | HTML size | Form in static HTML | RSC streaming | |---|---|---|---| | Headless Chrome / bot | 44KB | yes (SSR'd) | no | | Real Chrome / Firefox | 51KB | no (RSC only) | yes |
For real browser UAs, the login form is only in the React Server Components streaming payload, not in the initial static HTML. RSC streaming requires a live HTTP connection that delivers component data progressively.
Why this is (or was) a defense: evilginx-style proxies buffer the entire response body before forwarding (ioutil.ReadAll), converting chunked streaming to a single Content-Length response. React's RSC decoder sees the stream end before it expected, throws Error("Connection closed."), and the ErrorBoundary renders "Something went wrong." No form, no phish.
For about a week we thought this was a meaningful defense, real-browser users could not be phished by raw evilginx, only headless/automated UAs could complete the flow.
Then we put a Cloudflare orange-cloud in front of the proxy and the form rendered fine in real Chrome.
The reason, as best we can tell, is that Cloudflare's response handling between origin and edge restores enough streaming semantics that React doesn't see the stream truncate. The CDN inadvertently fixes the buffering issue the proxy created.
The practical attack-surface implication: RSC streaming as an AiTM defense only deters operators running raw evilginx behind a public IP. Operators using Cloudflare (overwhelmingly common, both for IP masking and free TLS) see the defense bypassed by their own CDN's response handling. Yahoo can't rely on RSC as a meaningful defense unless they detect and reject CDN-fronted requests, which they don't.
What an attacker captures (real-world reference point)
A single 5-minute scrape against a captured Yahoo account in our test produced:
- 45 inbox messages with subject, sender, date, snippet
- 63 unique correspondent email addresses
- Full sent-mail history
- Contact list
Provider distribution of the correspondents:
- 12 on Google Workspace / Gmail
- 10 on Microsoft 365
- 1 on Yahoo / AOL
- 40 on banks, ag-tech SaaS, marketing systems, miscellaneous
What this tells you: the captured Yahoo account is a graph-edge into Google- and Microsoft-protected counterparties. Compromise of the "soft" provider opens BEC and thread-aware spearphishing surface into the harder providers via trust-graph reputation. The captured contact list is the attacker's target list for lateral phishing.
This is the certain blast radius, independent of whether the attacker successfully escalates to configuration changes.
Yahoo's risk engine signals
During the live AiTM capture, Yahoo's risk classifier populated these hidden fields on the challenge-selector page:
secondChallengeReason = SUSPICIOUS_WITH_IP_PROXYchr(10)challengeIndexes = 202,650,701SUSPICIOUS_WITH_IP_PROXY fires when the originating IP doesn't match the user's typical profile (cloud / VPS / proxy ASN, unusual geo). It's exactly what an AiTM lure server produces.
If you have access to Yahoo enterprise sign-in telemetry, or you're tailing the user's account activity log directly, any auth event where this classifier fired is high-confidence AiTM. The attacker's proxy IP triggered it; the victim's real browser would not.
The high-risk-user trap page (/account/review/high-risk-user) sometimes renders post-auth. Yahoo issues the session cookies before showing the trap page. From an attacker's perspective the capture is already complete by the time the trap renders. Trap-page activity in the sign-in log is itself a high-signal event since legitimate users rarely encounter it.
MFA bypass detail
Yahoo's challenge-selector offers three channels:
| Index | Channel | AiTM-vulnerable? | |---|---|---| | 202 | Email to recovery address | Yes, attacker waits, victim types code into proxy | | 650 | WhatsApp | Yes, same, E2E encryption doesn't matter when the victim types it into the wrong page | | 701 | More options (TOTP / WebAuthn) | TOTP yes, WebAuthn no |
WebAuthn / passkeys are the only MFA channel that protocol-level prevents this attack. The authenticator signs a challenge that binds to the real origin domain. A proxy on a lookalike domain cannot satisfy the challenge.
Yahoo supports WebAuthn (isWebAuthnSupported: true in the login form's deviceCapability blob). Enrollment is at the account-security page. We strongly recommend it for any user who values their Yahoo account. See the step-up authentication and IR runbook posts in this bundle for the rest of the defensive stack.

Yahoo serves this warning to users post-login, recommending 2-step verification. The product team clearly knows AiTM is a threat against their users. The recommendation, "2-step verification," is exactly the MFA option AiTM walks straight through. Passkey enrollment is the option that would actually break the attack, and it's the option the warning doesn't recommend.
Status and revision
This threat model was validated end-to-end against production Yahoo Mail on 2026-05-14. The Cookie-Editor replay vector, step-up authentication observation, and CDN-bypass-of-RSC findings are all from that engagement. We'll revise if Yahoo changes any of these behaviors, please send a note via the site contact form if you observe deviation from what's described here.