Redirect target comes from the caller

The destination of a redirect is taken from the request without being checked. An attacker can send a link that starts with your domain and ends on theirs, which is what makes a phishing page credible - and in an OAuth callback it hands the authorisation code to whoever asked. Resolve the target against your own origin and refuse anything else.

medium likely application source OWASP A01:2021 / CWE-601

What it looks like

MEDIUM likely Redirect target comes from the caller A01:2021 app/api/proxy/route.ts:50:5 48 │ // open-redirect 49 │ if (next) { 50 │ redirect(next) │ ~~~~~~~~~~~~~~ destination chosen by the caller 51 │ }

From app/api/proxy/route.ts in the fixture suite. The fixture test asserts this finding.

How to fix it

Resolve the target against your own origin and refuse anything that lands elsewhere. Do not use a startsWith('/') check: '//evil.com' passes it and leaves the site.

// lib/safe-redirect.ts
export function safeRedirect(target: unknown, base: string, fallback = '/'): string {
  if (typeof target !== 'string') return fallback
  try {
    const resolved = new URL(target, base)
    // Same origin only. This rejects '//evil.com', 'https://evil.com',
    // and 'javascript:' alike. A leading-slash test does not: the browser
    // reads '//evil.com' as a URL to another host.
    return resolved.origin === new URL(base).origin ? resolved.pathname + resolved.search : fallback
  } catch {
    return fallback
  }
}

The fix for your framework

Choose the API used by your project.

Check your own repository

npx owlwarden scan --preset deep
npx owlwarden explain open-redirect

explain prints the rule and fixes in the terminal. It does not use the network.

All 25 rules / owlwarden