Fix redirect target comes from the caller in NestJS

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 NestJS CWE-601 / OWASP A01:2021

The vulnerable pattern in NestJS

MEDIUM likely Redirect target comes from the caller A01:2021 src/users/users.controller.ts:67:5 65 │ go(@Query() query: { next?: string }, @Res() res: Response) { 66 │ // open-redirect - `query` is a universal request-source name. 67 │ res.redirect(query.next as string) │ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ destination chosen by the caller 68 │ }

This finding comes from the NestJS fixture in the owlwarden test suite. The whole redirect target comes from the request, so a link to this endpoint can send a visitor anywhere. The URL they click genuinely belongs to you, which is what makes the page they land on convincing - and on an OAuth callback the authorisation code goes with them.

The corrected handler

Validate in the controller, or put the check in a pipe so every redirect gets it.

@Get('login')
@Redirect()
login(@Query('next') next: string) {
  return { url: safeRedirect(next, this.config.publicUrl) }
}

If you are not using NestJS

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.

Check your own repository

npx owlwarden scan
npx owlwarden explain open-redirect

Runs on your machine. No account, no telemetry, no network unless you ask. In CI, SARIF uploads to code scanning and the exit code is the gate.

Other NestJS checks

Rules with a tested NestJS example.

open-redirect for every framework / All rules / owlwarden