Tirup Mehta
Tirup Mehta
WritingOpen redirect vulnerabilities explained with practical examples

Open redirect vulnerabilities explained with practical examples

Essay/22.Jul.2026/3 min read
#cybersecurity#appsec#web-security#vulnerability-research
← All Articles
TL;DR

Open Redirect vulnerabilities (CWE-601) occur when an application accepts untrusted input to construct redirection targets. While often dismissed as low-severity cosmetic bugs, parser differentials and protocol handling quirks can turn simple redirects into critical OAuth account takeovers, Cross-Site Scripting (XSS), and Server-Side Request Forgery (SSRF) bypasses.

Redirection mechanisms are fundamental to web applications—routing unauthenticated users to identity providers, processing post-checkout landing pages, and switching geographic localizations. When an endpoint trusts user-supplied parameters to determine the Location response header without rigorous validation, attackers can redirect victims to malicious destinations under the implicit trust of the legitimate domain.

Vulnerability Classification

CWE-601: URL Redirection to Untrusted Site ('Open Redirect') • CVSS v3.1: 4.7 – 8.1 (Variable based on token leakage and auth chains) • RFC 3986 Section 3: URI Generic Syntax Specification

The Anatomy of Vulnerable Endpoints

A typical vulnerable pattern involves handling query parameters like next, return_to, or redirect_uri without structural validation:

controllers/auth.ts Vulnerable Implementation
import { Request, Response } from 'express';

export function handleLoginRedirect(req: Request, res: Response) {
  const target = req.query.return_url as string;
  
  // FLAW: Direct header reflection without origin validation
  if (target) {
    return res.redirect(302, target);
  }
  
  return res.redirect('/dashboard');
}

Bypass Techniques & Parser Differentials

Developers often attempt to sanitize redirect parameters with flawed regular expressions or prefix checks. In production security audits documented on tirup.in, we repeatedly observe common parser differential bypasses:

Vector / Payload Bypass Mechanism Target Parser Vulnerability
//evil.com/login Protocol-relative URL Browser interprets as https://evil.com
/\evil.com Backslash normalization WebKit/Blink normalize backslash to forward slash
https://trusted.com@evil.com Userinfo ambiguity Everything before @ parsed as credentials
https://trusted.com.evil.com Prefix substring match Naïve target.startsWith("https://trusted.com")
javascript:alert(1) Scheme execution DOM sinks evaluating window.location = target
Critical Escalation: OAuth 2.0 Token Leakage

When authorization servers allow wildcard redirect URIs or loose subpath matching, an open redirect on the callback domain allows attackers to capture authorization codes or access tokens via the Referer header or URI fragment manipulation.

Defense in Depth: Deterministic Validation

The only reliable defense against open redirects is deterministic URL decomposition. Instead of regex blacklists, parse the URL using the standard WHATWG URL API and enforce strict origin allowlists or relative path guarantees:

lib/security/redirect.ts Production Patch
const ALLOWED_ORIGINS = new Set([
  'https://tirup.in',
  'https://blogs.tirup.in',
]);

export function getSafeRedirectUrl(rawUrl: string | undefined, defaultPath = '/'): string {
  if (!rawUrl || typeof rawUrl !== 'string') {
    return defaultPath;
  }

  // Enforce relative paths safely
  if (rawUrl.startsWith('/') && !rawUrl.startsWith('//') && !rawUrl.includes('\')) {
    return rawUrl;
  }

  try {
    const parsed = new URL(rawUrl);
    
    // Strict scheme enforcement
    if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {
      return defaultPath;
    }

    // Origin allowlist check
    if (ALLOWED_ORIGINS.has(parsed.origin)) {
      return parsed.toString();
    }
  } catch {
    // Malformed URI string
    return defaultPath;
  }

  return defaultPath;
}
Core Implementation Checklist
  • Never reflect raw query parameters directly into HTTP 3xx Location headers.
  • Reject protocol-relative URLs (//example.com) and backslash escape variants (/\).
  • Validate schemes explicitly against https: to prevent javascript: and data: execution.
  • Use cryptographic state parameters in OAuth flows to tie redirection destinations to authenticated sessions.