DMARCPulse
All posts Robinhood incident: SPF, DKIM, DMARC and BIMI all passed — but the email was phishing

Robinhood phished its own customers with perfect email authentication — what actually broke

DMARCPulse Team
Email SecurityDMARCBIMIPhishingApplication SecurityIncident Analysis

On April 27, 2026, customers of US broker Robinhood found a security warning in their inbox. Sender: [email protected]. SPF, DKIM and DMARC all passed. For Gmail recipients, the BIMI logo appeared next to the message. The subject line: “Unrecognized Device Linked to Your Account — Review Activity Now”. The button led to robinhood[.]casevaultreview[.]com, a credential-harvesting page.

The email was not a spoofing attempt. It actually came from Robinhood’s own email infrastructure. Robinhood itself generated, signed and sent it. We took a closer look at the incident, because “someone did phishing” doesn’t explain it — and because the real lesson has nothing to do with email authentication. It sits one layer above.

The attack in three stages

Stage 1: Gmail dot-alias trick for recipient selection. Gmail treats [email protected] and [email protected] as the same address — both land in the same mailbox. Robinhood does not. From Robinhood’s database perspective those are two different email addresses, so both can register a separate account. The attackers took known Robinhood customer addresses from data leaks — for example [email protected] — and registered new accounts with modified dot notation. Robinhood’s system dutifully sent the confirmation email to [email protected]. That mail landed in the inbox of [email protected], the real Robinhood customer.

Stage 2: HTML injection via the device-metadata field. Robinhood’s login confirmation email includes fields like timestamp, IP address, approximate location and — this is the entry point — a “Device:” field. The field is auto-populated. Robinhood reads the User-Agent header from the HTTP request used to register the account, or a device_name field from the API body for mobile apps.

A normal User-Agent looks something like this:

Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15
(KHTML, like Gecko) Version/17.0 Safari/605.1.15

Robinhood parses it, simplifies it, and writes something like “MacBook (Safari 17)” into the device field of the email. The crucial point: the client can set this header to whatever it wants. With curl, Burp, Postman or a simple script, that’s a one-liner.

The attackers replaced the User-Agent with HTML — roughly something like:

</td></tr><tr><td><h2>⚠ Unrecognized Device Linked to Your Account</h2>
We detected a login from an unfamiliar location.
<a href="https://robinhood.casevaultreview.com/verify">Review Activity Now</a></td></tr>

Robinhood writes that string straight into the HTML template of the confirmation email. At the recipient end, the mail client (Gmail, Outlook) interprets the HTML as markup — not as text. From the recipient’s perspective, it looks like a real security alert, with button and all.

Stage 3: Authentication does what it’s supposed to do. The email genuinely came from Robinhood’s mail servers. SPF checks: the sending IP is authorized. DKIM signs the finished mail body, including the injected HTML. DMARC verifies that the From-domain matches the signing domain: it does. As far as all three standards are concerned, the email is clean. It is clean — as a Robinhood-signed message. The defect doesn’t sit in the send path. It sits in what was written into the message before the send path got hold of it.

Why this is a classic application-security flaw

HTML injection in email templates is the same family as cross-site scripting (XSS) on web pages — the difference is only that the rendering happens in the recipient’s mail client, not in a browser on a website. The defect lies in a step that every output-security framework flags as critical: user input is interpolated directly into the template, with no escaping.

The fix is straightforward. Before a user-controlled value is placed into an HTML body, the five HTML special characters must be replaced:

  • < becomes &lt;
  • > becomes &gt;
  • & becomes &amp;
  • " becomes &quot;
  • ' becomes &#39;

The phishing payload then becomes plain text — the recipient’s mail client visibly displays </td></tr><tr><td><h2>⚠ Unrecognized... as literal characters, not as a rendered block. That would be unusual enough for a recipient to pause — but it would not render a phishing link.

How different template engines handle this

This is the practical takeaway for anyone who sends transactional email. The defaults vary considerably:

Mustache and Handlebars. The standard {{value}} operator escapes automatically. Inserting raw HTML deliberately requires {{{value}}} (triple braces). The unsafe form is explicit — and someone has to consciously type three braces to introduce the defect.

Jinja2 (Python). By default, nothing is escaped unless autoescape=True is set. Web frameworks like Flask and Django turn autoescape on by default; using Jinja2 directly in a standalone email script does not. A classic foot-gun.

ERB (Ruby on Rails). Rails has automatic HTML escaping in views since version 3. That applies only to plain strings — not to ones explicitly marked as html_safe. Anyone who calls .html_safe on a user-supplied value has consciously turned the protection layer off.

Twig (PHP/Symfony). Auto-escape is on by default. Disabling requires {{ value|raw }}. Explicit again, deliberate again.

Razor (.NET). Similar to ERB — @value escapes automatically, @Html.Raw(value) bypasses it.

String interpolation or concatenation in the host language. Building mail bodies with f"<td>{value}</td>" in Python or `<td>${value}</td>` in JavaScript provides no automatic protection at all. This is — out of convenience — more common than people would expect.

For Robinhood, the defect appears to have lived in the last category. BleepingComputer reports that Robinhood did not fix the bug by adding sanitization after the fact, but by removing the device field from the email entirely. That is the brutal solution — faster than wiring in a sanitizer, but it also says: they preferred to delete the field rather than touch the template pipeline. That points to structural problems, not a single bug.

The lessons from this incident

Three points worth keeping:

First, email authentication is not a defense against compromised content. SPF, DKIM and DMARC say: the email really comes from the stated domain. They say nothing about whether the content is meaningful, harmless or trustworthy. Anyone who runs a platform that embeds user input into transactional email can have their own domain weaponized as a phishing channel — with a clean auth record.

Second, every user-controlled field in an outgoing email template is a potential phishing-delivery vehicle. Not just obvious fields like display name or note. Also unobtrusive metadata like User-Agent, device name, location, even timezone information, when it originates from a client request. During an audit, it is worth listing every place where the email body interpolates input from outside the system.

Third, the Gmail dot-alias trick is a rare but elegant amplifier. Robinhood could have reduced account creation to “canonical” email addresses (ignoring dots before the @ for Gmail addresses). The attackers would then have received their own emails, not the victims’. That is a single line in input validation. Email-address normalization is well known in the email industry, but rarely applied in anti-fraud contexts.

What is unsettling about this incident

The auth headers were all green. The domain was real. The logo appeared because of BIMI. Standard phishing-detection heuristics — odd spelling, wrong domains, missing signatures — would have found nothing here. The recipient had no technical signal that something was off, except for the email content itself, which felt slightly strange to attentive readers. Attentiveness alone is not a security strategy.

What makes this attack remarkable is the asymmetry between protection and bypass. Robinhood invested in DKIM, SPF, DMARC and BIMI — that is the right investment, and it works against most phishing vectors. But the bypass cost: a User-Agent string and a dot in an email address. Both are hours of work.

If you are in the platform-operator role and send confirmation emails, login alerts or similar transactional communication, you can close this risk with reasonably contained effort: output-encoding at every template interpolation, email normalization at account creation, regular auditing of every field that flows into outbound mail. It sounds like standard hygiene. The Robinhood incident shows that this hygiene is not yet practiced everywhere.

A note on what DMARCPulse can and cannot do here

We build a DMARC monitoring service, so the honest framing matters. DMARCPulse will not detect HTML injection inside your own transactional email templates — that is application-layer work, owned by your engineering team. What DMARCPulse does is verify the foundation: it makes sure SPF, DKIM, DMARC, MTA-STS, TLS-RPT and BIMI are configured correctly, and it surfaces every sender that is using your domain — including the unauthorized ones.

The Robinhood incident makes the case for both layers. Once the email-auth foundation is solid, every phishing message a recipient sees is either spoofed (and gets rejected) or authenticated (and is then trusted). The “authenticated and trusted but malicious” case is what the application layer has to handle. Skipping the foundation does not save you the application work — it just adds a second class of phishing on top.

If you want to know whether your domain’s foundation is in shape today, our public domain check is a 30-second start. From there, DMARCPulse gives you continuous monitoring, sender visibility and actionable recommendations with copy-paste DNS values.


Sources: BleepingComputer, Help Net Security, The National CIO Review, Protos — coverage from April 27–28, 2026. Robinhood statement on X, April 27, 2026.