Skip to main content
Back to blog
March 7, 2026|8 min read|Antoine Duno

Open Redirect Vulnerability: Risks, Examples & Prevention

An open redirect vulnerability allows attackers to weaponize your trusted domain for phishing campaigns, OAuth token theft, and SSRF chains. This guide explains how they work and how to eliminate them.

ZeriFlow Team

1,295 words

Open Redirect Vulnerability: Risks, Examples & Prevention

An open redirect vulnerability exists when a web application accepts a URL as a parameter and redirects users to that URL without validating whether it's a safe destination. While it might seem like a low-severity issue, open redirects are consistently abused for sophisticated phishing attacks, OAuth flow hijacking, and as a component in SSRF exploit chains — all leveraging the trust users place in your domain.

<div class="zf-stat-callout" style="background:#0d1117;border:1px solid rgba(16,185,129,0.25);border-left:3px solid #10b981;border-radius:4px;padding:16px 20px;margin:24px 0"> <p style="margin:0 0 4px;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.15em;color:#10b981;font-family:monospace">ZeriFlow Data — 12,400+ sites analyzed</p> <p style="margin:0;font-size:13px;color:#e2e8f0;line-height:1.6;font-family:monospace">In ZeriFlow's corpus of 12,400+ scanned sites, 72% score below 70/100 on security. Only 7% achieve a score above 85 — a threshold that corresponds to passing all OWASP-aligned header and configuration checks.</p> </div>

Check your application for open redirects and 79 other vulnerabilities — [scan free with ZeriFlow](https://zeriflow.com).


How Open Redirect Vulnerabilities Work

The pattern appears in countless web applications. After login, send users to where they were going. After an action, redirect back. It looks innocent:

https://legitimate-company.com/login?next=/dashboard
https://legitimate-company.com/logout?redirect=https://legitimate-company.com/

The vulnerability arises when the next or redirect parameter isn't validated:

python
# Vulnerable Python/Flask example
from flask import redirect, request

@app.route('/login', methods=['POST'])
def login():
    # ... authenticate user ...
    next_url = request.args.get('next', '/')
    return redirect(next_url)  # DANGEROUS: redirects to any URL

An attacker crafts:

https://legitimate-company.com/login?next=https://evil-phishing-site.com

The user authenticates on the real site, then gets redirected to the attacker's page — which can be a pixel-perfect clone asking them to "re-enter" credentials. The browser address bar showed legitimate-company.com during authentication, so the user has no reason to be suspicious.


Why Open Redirects Are More Dangerous Than They Appear

Phishing Bypass

Email security gateways and anti-phishing tools look for malicious domains in URLs. An open redirect on a trusted domain becomes a proxy:

https://google.com/url?q=https://phishing.com  (a real, frequently abused open redirect)
https://accounts.legitimate-bank.com/login?return=https://evil.com

The email scanner sees accounts.legitimate-bank.com — a trusted domain — and allows the message through. Users see the trusted domain in their email and click confidently.

OAuth Token Theft

OAuth 2.0 is particularly vulnerable. An open redirect on the legitimate authorization server can be used to steal access tokens via the redirect_uri:

GET /oauth/authorize?
  client_id=myapp&
  response_type=token&
  redirect_uri=https://legitimate.com/callback?next=https://attacker.com

If redirect_uri validation is loose, the OAuth server might redirect to the legitimate callback, which then open-redirects to the attacker, leaking the token in the URL fragment.

SSRF Chain Component

An open redirect on your server can sometimes be chained with SSRF vulnerabilities. If a service follows redirects when fetching URLs, an SSRF protection that blocks direct requests to internal IPs can be bypassed by first hitting an open redirect that points to the internal address.

Credential Harvesting via Referrer

When users click a link from your open redirect to an attacker site, the Referer header includes the full URL — including any session tokens or sensitive data that were in the URL at redirect time.


Code Examples: Vulnerable vs Secure

Vulnerable Node.js/Express

javascript
// VULNERABLE
app.get('/callback', (req, res) => {
  const redirectTo = req.query.url;
  res.redirect(redirectTo); // no validation!
});

Vulnerable PHP

php
// VULNERABLE
$redirect = $_GET['url'];
header("Location: $redirect");
exit();

Secure: Allowlist Approach

python
from urllib.parse import urlparse
from flask import redirect, request, abort

ALLOWED_HOSTS = {'myapp.com', 'www.myapp.com', 'app.myapp.com'}

def is_safe_redirect(url):
    if not url:
        return False
    
    # Only allow relative URLs (no scheme/host)
    parsed = urlparse(url)
    if parsed.scheme or parsed.netloc:
        # Absolute URL — check against allowlist
        return parsed.netloc in ALLOWED_HOSTS
    
    # Relative URL — ensure it starts with /
    return url.startswith('/')

@app.route('/login', methods=['POST'])
def login():
    next_url = request.args.get('next', '/')
    if not is_safe_redirect(next_url):
        next_url = '/'
    return redirect(next_url)

Secure: Relative-Only Redirects

The simplest approach: only allow relative URLs (paths), never absolute URLs:

javascript
// Node.js — allow only relative redirects
function safeRedirect(res, url) {
  // Must start with / and not contain //
  // (// could be treated as protocol-relative URL)
  if (url && url.startsWith('/') && !url.startsWith('//')) {
    return res.redirect(url);
  }
  return res.redirect('/');
}

Gotcha: //evil.com/path is a valid protocol-relative URL — browsers will follow it to evil.com. Always check that the URL doesn't start with //.


Framework-Level Protections

Django

Django's django.utils.http.url_has_allowed_host_and_scheme provides safe redirect validation:

python
from django.utils.http import url_has_allowed_host_and_scheme
from django.http import HttpResponseRedirect

def login_view(request):
    next_url = request.GET.get('next', '/')
    allowed = url_has_allowed_host_and_scheme(
        url=next_url,
        allowed_hosts={request.get_host()},
        require_https=request.is_secure()
    )
    if not allowed:
        next_url = '/'
    return HttpResponseRedirect(next_url)

Ruby on Rails

ruby
# Safe redirect helper
def safe_redirect(url)
  uri = URI.parse(url) rescue nil
  if uri && uri.relative?
    redirect_to url
  else
    redirect_to root_path
  end
end

Spring Boot (Java)

java
@GetMapping('/callback')
public String callback(@RequestParam String next, HttpServletResponse response) {
    URI uri = URI.create(next);
    if (uri.isAbsolute()) {
        return 'redirect:/'; // block absolute URLs
    }
    return 'redirect:' + next;
}

Detecting Open Redirects in Your Codebase

Search for common redirect patterns with user-supplied input:

bash
# Find potential open redirects in Python
grep -rn 'redirect(request\.' . --include='*.py'
grep -rn 'redirect(.*GET\[' . --include='*.py'

# Find in JavaScript/Node
grep -rn 'res\.redirect(req\.' . --include='*.js'

# Find in PHP
grep -rn 'header.*Location.*\$_GET' . --include='*.php'

Also look for: 302, 301, window.location, document.location, location.href set to user-controlled values.


FAQ

Q: Is open redirect a high-severity vulnerability?

A: By itself, open redirect is typically classified as medium severity. However, context matters significantly. When combined with OAuth flows, it becomes critical (token theft). When leveraged for phishing against high-value targets (banking, enterprise SaaS), the real-world impact is high. Many bug bounty programs pay $500–$5,000 for open redirects depending on exploitability.

Q: Can I use a blocklist to prevent open redirects?

A: Blocklists are notoriously insufficient. Attackers use IP addresses, URL encoding, Unicode homoglyphs, and other techniques to bypass string-matching filters. Always use an allowlist approach — only permit redirects to known good destinations.

Q: Does meta http-equiv='refresh' create open redirects?

A: Yes. If user input is reflected in a meta refresh tag, it's an open redirect. The same validation rules apply. Additionally, meta refresh bypasses some X-Frame-Options protections.

Q: How do I find open redirects in my third-party dependencies?

A: Check your dependency tree for known open redirect CVEs using npm audit, pip-audit, or bundler-audit. For runtime detection, integrate a WAF rule that logs requests with next, url, redirect, return_to parameters containing external domains. ZeriFlow can also flag common open redirect patterns in HTTP responses.

Q: Are URL shorteners open redirects?

A: By design, yes — URL shorteners redirect to arbitrary destinations. This is why security tools flag them in phishing detection. If you build a redirect service, add phishing detection (Google Safe Browsing API), implement rate limiting, and log all redirects for abuse investigation.


Conclusion

Open redirect vulnerabilities sit at an interesting intersection: trivial to implement safely, yet consistently found in production applications. The fix is always an allowlist or relative-only redirect policy — a few lines of code that eliminates the entire attack vector.

The danger is in dismissing them as "low severity." A weaponized open redirect on a banking or enterprise SaaS domain can facilitate credential theft at scale, with a phishing success rate far higher than a link to an unknown domain.

[Scan your application with ZeriFlow](https://zeriflow.com) to check for open redirect indicators alongside 79 other security controls. Free, no account required — know your exposure before an attacker exploits it.

Ready to check your site?

Run a free security scan in 30 seconds.

Related articles

Keep reading