Problem
apps/web/src/app/(auth)/login/page.tsx line 9 uses only next.startsWith('/') to filter the redirect target. This passes //evil.com (protocol-relative open redirect) into the hidden form field.
The action layer (auth.ts:72-80) correctly rejects // prefixes, so no actual redirect to an external host occurs. But the page-level check is misleading and is one action-refactor away from becoming exploitable.
Fix
Apply the same complete guard at the page level:
const safeNext = next && next.startsWith('/') && !next.startsWith('//') && !next.startsWith('/\\')
? next
: undefined;
Problem
apps/web/src/app/(auth)/login/page.tsxline 9 uses onlynext.startsWith('/')to filter the redirect target. This passes//evil.com(protocol-relative open redirect) into the hidden form field.The action layer (
auth.ts:72-80) correctly rejects//prefixes, so no actual redirect to an external host occurs. But the page-level check is misleading and is one action-refactor away from becoming exploitable.Fix
Apply the same complete guard at the page level: