Unvalidated redirect URLs enable phishing attacks via your domain. Always validate against an allowlist or restrict to relative paths. [CWE-601 · A01:2021]
Why This Matters
prevents open redirect attacks used for phishing and credential theft
Impact: CRITICAL (prevents open redirect attacks used for phishing and credential theft)
Open redirects occur when an application redirects users to a URL provided in query parameters or request bodies without validation. Attackers use this to send users to phishing sites that appear to originate from your domain (e.g., yourapp.com/login?next=https://evil.com).
Incorrect (redirecting to unvalidated user input):
// ❌ Redirect to whatever the query param says// app/api/auth/callback/route.tsexport async function GET(request: Request) { const { searchParams } = new URL(request.url) const redirectUrl = searchParams.get('next') || '/' // Attacker crafts: /api/auth/callback?next=https://evil.com/steal-creds return Response.redirect(redirectUrl)}
// ❌ Also dangerous in Server Actions'use server'export async function login(formData: FormData) { await authenticate(formData) const next = formData.get('next') as string redirect(next) // Could redirect anywhere}
Correct (validate against an allowlist or ensure relative path):
// ✅ Only allow relative paths (same-origin redirects)export async function GET(request: Request) { const { searchParams } = new URL(request.url) const next = searchParams.get('next') || '/' // Ensure it's a relative path, not an absolute URL const safeUrl = next.startsWith('/') && !next.startsWith('//') ? next : '/' return Response.redirect(new URL(safeUrl, request.url))}
// ✅ Allowlist approach for known redirect targetsconst ALLOWED_REDIRECTS = ['/dashboard', '/settings', '/onboarding']export async function GET(request: Request) { const { searchParams } = new URL(request.url) const next = searchParams.get('next') || '/dashboard' const safeUrl = ALLOWED_REDIRECTS.includes(next) ? next : '/dashboard' return Response.redirect(new URL(safeUrl, request.url))}
Detection hints:
# Find redirect/rewrite using query params or user inputgrep -rn "redirect\|Response.redirect\|router.push\|router.replace" src/ --include="*.ts" --include="*.tsx" | grep -E "searchParams|formData|params|query"