The $6000 Yelp XSS Chain: How Cookie Smuggling Turned a Simple Reflection into Full Account Takeover
A deep, beginner-to-advanced breakdown of a high-impact XSS vulnerability on Yelp where cookie smuggling, unsafe reflection, and logic flaws chained together to enable credential theft and full account takeover.
Disclaimer
This write-up is provided strictly for educational and defensive purposes.
All vulnerabilities discussed were responsibly disclosed and have since been fixed.
Do not attempt to exploit systems you do not own or have explicit authorization to test.
Introduction
Some vulnerabilities look small on the surface. A reflected input here, a strange cookie behavior there. On their own, they might feel like “low severity” findings. But as every experienced security researcher eventually learns, impact is rarely about a single bug. It’s about how small mistakes interact.
This Yelp vulnerability is a perfect example.
What started as an unescaped cookie reflection escalated into a persistent cross-site scripting (XSS) chain, credential harvesting on the business login portal, and full account takeover through third-party authentication flows. The final bounty: $6000.
In this blog, we’ll break the entire chain down step by step, starting from fundamentals so beginners can follow, and going deep enough that experienced engineers and hunters can appreciate the nuance.
XSS Refresher: Why This Class of Bugs Still Matters
Cross-Site Scripting (XSS) allows an attacker to execute JavaScript in another user’s browser within the target site’s origin. That origin-level execution is what makes XSS so dangerous.
At a high level, XSS can lead to:
- Session hijacking
- Credential theft
- Account takeover (ATO)
- UI manipulation and phishing
- Abuse of authenticated APIs
There are three main types:
- Reflected XSS - Input reflected immediately in a response
- Stored XSS - Payload stored server-side and served later
- DOM-based XSS - Client-side execution via unsafe DOM handling
In this Yelp case, the vulnerability started as reflected XSS, but clever chaining made it behave like a persistent stored XSS.
The Core Bug: Unescaped Reflection of the guvo Cookie
The root of the vulnerability was simple but dangerous.
Yelp was embedding the value of a cookie named guvo directly into JavaScript objects rendered on pages such as:
https://www.yelp.comhttps://biz.yelp.com/login
The value was not properly escaped before being injected into the page.
This meant that if an attacker could control the value of guvo, they could inject executable JavaScript into the page context.
Conceptually, the problem looked like this:
- Server reads
guvocookie - Server injects it into inline JavaScript
- Browser executes whatever is inside
On its own, this is already serious. But the real question was:
How does an attacker control the guvo cookie for another user?
The Canary Parameter: An Unexpected Cookie Setter
Yelp exposed a query parameter named canary.
When a user visited a URL like:
The server responded with a Set-Cookie header, setting a cookie similar to:
This appeared to be a diagnostic or feature-flag mechanism.
By itself, this wasn’t a vulnerability. But it gave attackers something powerful:
A way to plant a cookie in a victim’s browser just by getting them to click a link.
At this point, attackers still couldn’t directly set guvo. That’s where the next flaw came in.
Cookie Smuggling: Parsing Gone Wrong
HTTP cookies are supposed to be parsed using semicolons (;) as delimiters:
Yelp’s backend, however, was incorrectly splitting cookies on spaces.
This meant that a cookie value like:
was interpreted as two separate cookies.
This parsing flaw enabled cookie smuggling.

Smuggling guvo Through the Canary Cookie
Here’s where the chain becomes elegant.
The attacker crafted a URL like this:
The server set a single cookie:
But when Yelp later parsed the Cookie header, it split on spaces and treated this as:
yelpmainpaastacanary=asdfguvo=</script><script>alert(1)</script>
At this point:
- The attacker successfully injected a controlled
guvocookie - The value was reflected unescaped
- JavaScript executed in the Yelp origin
XSS achieved.
From Reflected to Persistent XSS
This wasn’t a one-time execution.
Because cookies persist:
- Victim clicks the link once
- Malicious cookie is stored
- Payload executes on every affected page visit
That’s what turned a reflected issue into persistent XSS behavior.
This persistence dramatically increased impact.

Proof of Concept #1: Keylogging on Business Login
The Yelp business portal (biz.yelp.com/login) contains sensitive login forms.
With XSS execution on that page, the attacker injected JavaScript that:
- Waited for the page to load
- Hooked email and password input fields
- Listened for typing and submission
- Exfiltrated credentials to an attacker-controlled endpoint
Because the script executed inside Yelp’s origin, browser security controls did not block it.
This enabled real-time credential theft.
Proof of Concept #2: Account Takeover via Google Linking
Yelp supports Google account linking.
The flow involved:
- CSRF tokens embedded in pages
- A POST request linking a Google
id_tokento a Yelp account
Using XSS, the attacker:
- Fetched a page containing the CSRF token
- Extracted the token via JavaScript
- Submitted a forged request linking the attacker’s Google account to the victim’s Yelp account
Once linked, the attacker could log in as the victim using Google Sign-In.
This was a full account takeover.

Why This Bug Was High Severity
This vulnerability:
- Required only a click
- Persisted across sessions
- Allowed credential theft
- Enabled account takeover
- Affected both consumer and business accounts
That combination justified the $6000 bounty.
Defensive Lessons for Engineers
1. Never Reflect Untrusted Input into Executable Contexts
Cookies, headers, query parameters - all are attacker-controlled.
Always escape based on context.
2. Follow Standards When Parsing Protocols
Cookie parsing bugs are subtle and dangerous.
If you re-implement protocol parsing, you will almost certainly get it wrong.
3. Assume Features Will Be Chained
The canary parameter wasn’t dangerous by itself.
Neither was cookie reflection alone.
Security failures compound.
4. CSP Is Not Optional
A strict Content Security Policy could have prevented inline script execution even after reflection.
Defense-in-depth matters.
Hunting Takeaways for Researchers
- Look for non-obvious input sources like cookies
- Test how servers parse edge cases
- Chain low-impact issues creatively
- Think like a system, not a scanner
Conclusion
This Yelp vulnerability wasn’t about a single clever payload. It was about curiosity, protocol knowledge, and chaining behavior that developers didn’t expect.
That’s what real-world web security looks like.
Small assumptions. Big consequences.
References
- OWASP Cross-Site Scripting Prevention Cheat Sheet
- RFC 6265 - HTTP State Management Mechanism
- PortSwigger Web Security Academy - XSS
- Publicly disclosed HackerOne reports (Yelp)