Open Redirect
An open redirect is a web vulnerability that lets an attacker use a trusted site’s URL to send visitors to any external destination. It happens when a page reads the redirect target from user-controlled input, usually a query parameter, and forwards the browser there without checking where it points. MITRE tracks the flaw as CWE-601, “URL Redirection to Untrusted Site”, and OWASP also calls it an unvalidated redirect.
Safe: https://example.com/login?next=/dashboard
Exploited: https://example.com/login?next=https://evil-site.test/fake-login
Both links start with the same trusted domain. Only the second one lands the visitor on an attacker’s page.
Why Open Redirects Matter
The risk is borrowed trust, not the redirect itself. A victim sees a legitimate hostname in the link, hovers over it, and clicks. The destination is controlled by someone else.
That makes open redirects useful to attackers in three ways:
- Phishing. The link in the email genuinely belongs to the bank, retailer, or SaaS product being spoofed. Users trained to check the domain before clicking still get caught.
- Security filter bypass. Email gateways, chat apps, and ad networks judge a link by its visible hostname. A redirect through an allowlisted domain slips past those checks.
- Exploit chains. OAuth and SSO flows hand an authorization code to a
redirect_uri. A loose redirect in that flow can leak tokens, session identifiers, or password reset links to an attacker’s server.
Rated on its own, an open redirect is usually medium severity. Chained into an authentication flow, it becomes an account takeover. OWASP groups it under Broken Access Control in the current Top 10.
How an Open Redirect Works
The vulnerability appears wherever code passes user input straight into a redirect. A typical vulnerable handler looks like this:
# Vulnerable: the destination comes straight from the request
target = request.args.get("next")
return redirect(target)
The parameter exists for a good reason. Sites use it to return users to the page they wanted after login, checkout, or a language switch. The bug is the missing check between reading the value and acting on it.
Parameter names to look for during a review: next, url, redirect, redirect_uri, return, returnUrl, dest, destination, continue, goto, callback, and single letters like r or u.
Open Redirect Example
Attackers rarely paste a clean external address into the parameter, because naive filters catch it. These variants defeat most string checks:
| Payload | Why it works |
|---|---|
//evil-site.test |
Protocol-relative URL. No scheme, so a “must not contain http” check passes, but browsers treat it as an absolute address. |
https://[email protected] |
Everything before the @ is treated as credentials. The real host is what follows. |
https://example.com.evil-site.test |
A “starts with the domain” check passes. The actual registrable domain is different. |
https:/\evil-site.test |
Mixed slashes. Browsers normalize them, many validators do not. |
%2f%2fevil-site.test |
Encoded slashes that become a protocol-relative URL after the framework decodes the parameter. |
A prefix check such as if target.startswith("https://example.com") fails against the second and third rows. That is why validation has to run on the parsed URL, not the raw string.
Types of Open Redirects
Three implementations carry the same flaw:
- Header-based. The server returns a 301, 302, or 307 with a
Locationheader built from user input. The most common form. - DOM-based. Client-side JavaScript assigns the parameter to
window.location,location.href, orlocation.replace(). The redirect never touches the server, so server-side logs and firewall rules miss it. - Meta refresh. The page renders a
<meta http-equiv="refresh">tag with an unvalidated URL. Older but still present in legacy templates.
How to Prevent Open Redirects
Never redirect to a raw user-supplied URL. Apply these controls in order of strength:
- Accept relative paths only. Require the value to start with a single slash and reject anything containing a scheme, a host, a backslash, or a leading double slash. This covers most login and checkout return flows.
- Validate against an allowlist. Where external redirects are genuinely needed, keep a fixed list of approved hosts and compare against the parsed hostname, never a substring of the raw string.
- Use indirect references. Map destinations to short IDs server-side and accept a value like
next=7instead of a URL. The attacker has nothing useful to tamper with. - Pin OAuth redirect URIs exactly. Match
redirect_uriagainst registered values character for character. No wildcards, no prefix matching, no subdomain flexibility. - Fail to a safe default. When validation rejects a value, send the user to a fixed server-decided page rather than passing the input through.
- Show an interstitial for real outbound links. If redirecting out to third-party domains is a product feature, warn the user and display the full destination first.
Short links deserve the same scrutiny, because a shortener hides the destination by design. A short link is not itself an open redirect, since the owner sets a fixed target, but attackers chain shorteners in front of vulnerable redirects to hide the payload. Platform-level link protection that blocks malicious destinations closes that gap for the links you publish.
Frequently Asked Questions
What is an open redirect?
An open redirect is a flaw that lets anyone use a trusted site’s URL to forward visitors to an arbitrary external page. The site takes the destination from a query parameter and follows it without validation. Because the visible domain is legitimate, the link passes both human inspection and most automated filters.
What is an unvalidated redirect?
Unvalidated redirect is the OWASP name for the same issue, taken from its “Unvalidated Redirects and Forwards” guidance. MITRE catalogues it as CWE-601, “URL Redirection to Untrusted Site”. The terms are interchangeable in vulnerability reports and scanner output.
How serious is an open redirect vulnerability?
On its own it usually scores medium severity, since it needs a victim to click. Severity rises sharply when the redirect sits inside an authentication flow. A loose redirect_uri in OAuth can leak an authorization code and lead to full account takeover.
How do you test for an open redirect?
Find every parameter that controls navigation, then submit test values such as a protocol-relative address, a URL with an @ before the real host, and one with mixed slashes. Follow the response without automatic redirects and read the Location header. If it points off-domain, the parameter is vulnerable. Check client-side redirects too, since those never appear in server logs.
How do you prevent open redirects?
Stop accepting full URLs. Allow relative paths only, or map destinations to IDs resolved on the server. When external redirects are required, validate the parsed hostname against an allowlist and fail to a fixed default when the check does not pass.
Before you click or publish a shortened link, expand it with the free URL shortener preview tool at linkutm to see the real destination.