@@ -3,7 +3,7 @@ import { useState } from "react";
33import Link from "next/link" ;
44import { dispatchAuthStateChange } from "@/utils/authState" ;
55
6- const DEFAULT_REDIRECT_PATH = "yugioh/my-collection" ;
6+ const DEFAULT_REDIRECT_PATH = "/ yugioh/my-collection" ;
77const LOCALHOST_FALLBACK_ORIGIN = "http://localhost:3000" ;
88
99const getBaseOrigin = ( ) => {
@@ -22,37 +22,42 @@ const getBaseOrigin = () => {
2222 return LOCALHOST_FALLBACK_ORIGIN ;
2323} ;
2424
25- const resolveRedirectPath = ( queryParam ) => {
26- const baseOrigin = getBaseOrigin ( ) ;
25+ const BLOCKED_PATHS = new Set ( [ "/login" , "/register" , "/api" , "/api/auth/login" , "/api/auth/register" ] ) ;
2726
27+ const resolveRedirectPath = ( queryParam ) => {
2828 if ( typeof queryParam !== "string" ) {
2929 return DEFAULT_REDIRECT_PATH ;
3030 }
3131
32- const sanitizedParam = queryParam . trim ( ) ;
32+ const trimmed = queryParam . trim ( ) ;
3333
34- if ( ! sanitizedParam || sanitizedParam . startsWith ( "/" ) ) {
34+ if ( ! trimmed ) {
3535 return DEFAULT_REDIRECT_PATH ;
3636 }
3737
38- if ( sanitizedParam . startsWith ( "/" ) ) {
39- return sanitizedParam . startsWith ( "/api" )
40- ? DEFAULT_REDIRECT_PATH
41- : sanitizedParam ;
38+ // Reject protocol-relative, absolute URLs to other origins, and javascript: style values early.
39+ if ( / ^ ( [ a - z A - Z ] [ a - z A - Z \d + \- . ] * : ) ? \/ \/ / . test ( trimmed ) ) {
40+ return DEFAULT_REDIRECT_PATH ;
4241 }
4342
43+ const relativePath = trimmed . startsWith ( "/" ) ? trimmed : `/${ trimmed } ` ;
44+
4445 try {
45- const candidate = new URL ( sanitizedParam , baseOrigin ) ;
46+ const baseOrigin = getBaseOrigin ( ) ;
47+ const candidate = new URL ( relativePath , baseOrigin ) ;
4648
4749 if ( candidate . origin !== baseOrigin ) {
4850 return DEFAULT_REDIRECT_PATH ;
4951 }
5052
51- if ( candidate . pathname . startsWith ( "/api" ) ) {
53+ const { pathname } = candidate ;
54+
55+ if ( BLOCKED_PATHS . has ( pathname ) || pathname . startsWith ( "/api" ) ) {
5256 return DEFAULT_REDIRECT_PATH ;
5357 }
5458
55- return `${ candidate . pathname } ${ candidate . search } ${ candidate . hash } ` || DEFAULT_REDIRECT_PATH ;
59+ const safePath = `${ pathname } ${ candidate . search } ${ candidate . hash } ` . trim ( ) ;
60+ return safePath || DEFAULT_REDIRECT_PATH ;
5661 } catch {
5762 return DEFAULT_REDIRECT_PATH ;
5863 }
0 commit comments