Disclaimer:
This write-up is for educational purposes only. The vulnerability described below was discovered by another security researcher and disclosed on HackerOne (Report #3599248). I did not find this bug myself โ I'm simply studying and explaining it to help others learn. Full credit goes to the original reporter.
๐ Reference: HackerOne Report #3599248
๐ง The Gist (in plain English)
Picture this:
You just logged into lovable.dev. You get a link like:
https://lovable.dev/auth/post-login?redirect=/dashboard
That redirect parameter tells the app where to send you after login. Normally, it should only send you to pages inside lovable.dev โ like /dashboard or /settings.
But someone found a trick that makes the app send you to any website โ even though the devs already tried to fix it once before.
๐ The Original Fix (from report #3581815)
The first bug used something like /\\google.com to escape the redirect filter.
The devs blocked /\\ and /%5C (backslash patterns).
But blocking bad patterns is like playing whack-a-mole.
You block one, and another pops up.
๐ The Bypass (this report)
The new payload is:
/..//google.com
Full URL:
https://lovable.dev/auth/post-login?redirect=/..//google.com
What happens step-by-step:
- You're logged in to
lovable.dev. - You click that special link (looks like it's staying inside the site).
- The server sees
/..//google.com. - It normalizes (cleans up) the path:
/..//google.comโ removes/..โ becomes//google.com
- Server sends a redirect:
Location: //google.com - Browser sees
//google.comand thinks: - "Oh, two slashes means use the same protocol (https) and go to google.com"
- ๐ You're now on
https://google.comโ an external site.
๐งจ Why This Is Dangerous (Impact)
This is not just "a weird redirect thing". It's a real phishing weapon:
- Trusted domain โ The link starts with
lovable.dev, so victims trust it. - Post-login โ You're already authenticated, so fake login pages look super convincing.
- Silent โ You don't notice you left the real site until it's too late.
Attackers could:
- Steal your session token via a fake login page.
- Show you a "Session expired, please re-enter password" popup (but it's their server).
- Redirect to a malicious site that looks exactly like Lovable.
๐ ๏ธ Why the Fix Didn't Work
The first fix used a denylist (blocking /\\ and /%5C).
Denylists almost always fail because there are infinite bypasses.
In this case, the bypass worked because:
- The server normalized
/..//into// - The browser interprets
//domain.comas a protocol-relative external URL - No one checked: "Wait, is this really an internal path after normalization?"
โ How to Actually Fix This (For Devs)
Never trust a denylist. Instead:
Option 1 (Safest): Allowlist
Only allow specific paths:
javascript
const allowed = ["/dashboard", "/settings", "/profile"];
if (!allowed.includes(redirect)) {
redirect = "/dashboard";
}Option 2 (More flexible but still safe)
Parse and validate the URL properly:
javascript
let url;
try {
url = new URL(redirect, "<https://lovable.dev>");
} catch (e) { /* invalid */ }
// Block if it has a hostname (external)
if (url.hostname !== "lovable.dev" && url.hostname !== "") {
// Reject โ this is an external redirect
}Option 3 (Block protocol-relative URLs)
If you see // at the start of the string after normalization โ reject it immediately.
๐ Final Takeaways (for learners)
Concept Example Path traversal /..// gets normalized to // Protocol-relative URL //google.com = https://google.com Denylist bypass Blocked /\\ but forgot ..// Proper fix Allowlist + parse URL + reject external domains
This is a classic open redirect that kept coming back because the fix was reactive, not proactive.
๐ Shoutout
Again, full credit to the original hacker who found this on HackerOne.
I'm just a curious learner breaking down their work to understand it better.
๐ Stay curious, stay ethical, and always validate redirects with an allowlist.