URL Redirection to Untrusted Site ('Open Redirect')
A web application accepts a user-controlled input that specifies a link to an external site, and uses that link in a Redirect.
An open redirect vulnerability occurs when an application takes user input and uses it to redirect the user to a different URL. Attackers can exploit this to redirect users to malicious sites.
How to fix this vulnerability
Prevention strategies for Open Redirect based on 4 Shoulder detection rules.
Validate redirect URLs against an allowlist of trusted domains
package main - import "net/http" - - func handler(w http.ResponseWriter, r *http.Request) { - target := r.URL.Query().Get("redirect") - // Vulnerable: redirect to user-controlled URL + import ( + "net/http" + "net/url" + ) + + var allowedHosts = map[string]bool{ + "example.com": true, + "app.example.com": true, + } + + func handler(w http.ResponseWriter, r *http.Request) { + target := r.URL.Query().Get("redirect") + u, err := url.Parse(target) + if err != nil || (u.Host != "" && !allowedHosts[u.Host]) { + http.Error(w, "Invalid redirect URL", http.StatusBadRequest) + return + } + // Safe: only allows relative paths or allowed domains http.Redirect(w, r, target, http.StatusFound) }
Validate redirect targets against an allowlist of permitted paths
- export function middleware(request) { - const redirectUrl = request.nextUrl.searchParams.get('redirect'); - if (redirectUrl) { - return NextResponse.redirect(redirectUrl); - } + const ALLOWED_PATHS = ['/login', '/dashboard', '/profile']; + + export function middleware(request) { + const redirect = request.nextUrl.searchParams.get('redirect'); + if (redirect && ALLOWED_PATHS.includes(redirect)) { + return NextResponse.redirect(new URL(redirect, request.url)); + } + return NextResponse.redirect(new URL('/', request.url)); }
Validate redirect URLs against an allowlist or enforce relative paths
const express = require('express'); const app = express(); - app.get('/redirect', (req, res) => { - const url = req.query.url; - res.redirect(url); + const ALLOWED_REDIRECTS = ['/home', '/dashboard', '/profile']; + + app.get('/redirect', (req, res) => { + const url = req.query.url; + if (ALLOWED_REDIRECTS.includes(url) || url.startsWith('/')) { + res.redirect(url); + } else { + res.redirect('/home'); + } });
Validate redirect URLs against a domain allowlist or use relative paths
from flask import request, redirect - - @app.route('/goto') - def goto(): - url = request.args.get('url') + from urllib.parse import urlparse + + ALLOWED_DOMAINS = {"myapp.com", "www.myapp.com"} + + @app.route('/goto') + def goto(): + url = request.args.get('url', '/') + parsed = urlparse(url) + if parsed.netloc and parsed.netloc not in ALLOWED_DOMAINS: + url = '/' return redirect(url)
Find vulnerabilities in your code
Use Shoulder to scan your codebase for URL Redirection to Untrusted Site ('Open Redirect') patterns. 4 rules.
# Scan with Shoulder CLI npx @shoulderdev/cli trust --cwe=601 # Or scan entire project npx @shoulderdev/cli trust .
Detection Rules (4)
What to watch for in code reviews
These patterns indicate potential URL Redirection to Untrusted Site ('Open Redirect') vulnerabilities. Look for these during code reviews and security audits.
Scan your codebase for URL Redirection to Untrusted Site ('Open Redirect')
Shoulder CLI finds vulnerable patterns across your entire codebase.