Open redirect high
Open Redirect (Unvalidated Redirect)
A redirect endpoint takes its destination from a user-controlled parameter with no allow-list, letting attackers bounce visitors off your domain to phishing.
What you see
Open redirect detected GET /redirect?url=https://evil.example.com Unvalidated redirect / forward (CWE-601)
What’s actually happening
A security scanner (Burp, ZAP, a pentest report) flags an endpoint like /redirect?url= or /login?next= as an open redirect. The URL starts on your trusted domain, then forwards to wherever the attacker put in the parameter. It gets used in phishing — the link looks like yours, the landing page isn't. It also shows up as a stepping stone in OAuth token-theft and as a way around naive referrer checks.
Common causes
- A redirect/forward endpoint reads ?url=, ?next=, ?return=, ?dest=, or ?continue= and sends a Location header straight from it with no validation.
- A login flow preserves a 'return to' URL across auth and trusts it blindly after the user signs in.
- Validation only checks that the value 'starts with /' but misses //evil.com (protocol-relative) or /\evil.com, both of which browsers treat as off-site.
- A blocklist approach tries to strip http:// but is bypassed by case, encoding (%2F%2F), or whitespace tricks.
- An allow-list compares with startswith and gets fooled by evil.com.yourdomain.com or yourdomain.com.evil.com.
How to fix it
- Allow-list, don't blocklistValidate the destination against an explicit allow-list of paths or hosts. For internal redirects, only accept relative paths and reject anything with a scheme or host. For external, match the host against a fixed set you control — exact host equality, not startswith/contains.
- Reject protocol-relative and backslash formsTreat //evil.com, /\evil.com, and https:evil.com as external. Parse the value with a real URL parser and inspect the resolved host; don't regex it by hand. A leading // is the classic bypass that 'must start with /' checks miss.
- Map tokens to URLs instead of passing URLsWhere you can, don't accept a URL at all. Pass an opaque key (?next=dashboard) and look up the real path server-side from a table. The user never controls a URL, so there's nothing to abuse.
- Default safe and log rejectsIf validation fails, redirect to a known-safe default (your homepage) rather than echoing the input. Log rejected destinations — a spike of weird hosts is someone probing the endpoint.
- Re-scan to confirmRe-run the scanner (ZAP/Burp) against the endpoint with the payloads from the original finding: //evil.com, https://evil.com, /%2F%2Fevil.com. Confirm each lands on your safe default, not the attacker host.
Stop it recurring
Never build a Location header from raw user input — map a token to a server-side path, or validate against an exact-match host allow-list.
Related errors