## TL;DR
Never redirect to a user-supplied URL as-is. Accept only relative paths, or parse the URL and check the host against an explicit allowlist. Most open redirects come from trusting a next or returnUrl parameter, and the fix is one validation function at every redirect point.

## The query

```text
how to prevent open redirects in your app
```

## Use this when

- A security report flags an open redirect in your login or logout flow
- You are building any redirect that takes a destination parameter
- You are reviewing redirect handling in an API or web app

## Not for

- SSRF (server-side request forgery, different vulnerability)
- Phishing detection or email filtering
- URL shortener abuse
- Authentication bugs

## Steps

### 1. Find every redirect that reads user input

Search the codebase for redirect calls that take a query parameter like next, redirect, returnUrl, or continue. Every one of those is a candidate.

Expected output: a list of redirect call sites, each marked safe or needing validation.

### 2. Prefer relative paths only

The simplest safe rule: accept only paths starting with a single slash, and reject anything else. No host, no scheme, no redirect off your domain possible.

Expected output: login and logout flows that only ever redirect within your own site.

### 3. If you must allow absolute URLs, parse and allowlist

Parse the URL with a real URL parser, then check the parsed host against an explicit allowlist of trusted domains. Reject anything that fails to parse or isnt on the list. Never match with string prefix checks like startsWith, because trusted.example.com.evil.example.com passes those.

Expected output: cross-domain redirects work only for listed partners; everything else falls back to a safe default page.

### 4. Neutralize the classic bypass tricks

After decoding, re-check for: protocol-relative URLs starting with two slashes, backslash variants that some browsers treat as slashes, and encoded slashes or dots that decode into a different host. Decode more than once to catch double-encoding, and re-validate after each decode.

Expected output: manual tests with tricky inputs stay on your domain; a scanner no longer flags the parameter.

### 5. For legitimate cross-domain needs, use signed tokens

Instead of passing the destination URL as a parameter, map a short token to the destination server-side (a lookup table or a signed value). The user sees an opaque token; the server decides where it goes.

Expected output: partner redirects work with no user-controllable URL anywhere in the flow.

## Variant phrasings

### unsafe redirect to user-supplied URL fix

Steps 2 and 3. Relative-path-only is the fastest fix; allowlisting is the flexible one.

### open redirect in login flow

The next parameter after login is the classic case. Validate it with step 2 before issuing the redirect.

### CWE-601 URL redirection to untrusted site

That is the formal name for this vulnerability. The checklist above is the standard remediation.

## Why it happens

Redirect-after-login is a convenience feature: remember where the user was going, send them back after auth. The destination gets passed as a parameter, and nobody validates it because the happy path always points at your own site. Attackers notice the parameter is trusted, and suddenly your login page is a launchpad for phishing that carries your domain's credibility.

## Edge cases

- Single sign-on flows that legitimately redirect off-domain: use the signed-token pattern from step 5.
- Mobile deep links and custom schemes: allowlist the scheme plus the host; custom schemes have their own parsing quirks.
- Open redirect chained with XSS or a login CSRF: fix the redirect first, then check whether the chained issue is reachable another way.
- Subdomain takeovers: an allowlisted subdomain you no longer control is an open redirect waiting to happen. Audit the list when you drop subdomains.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_B8A9z9LO6eZFlcAi07VFIA
