Skip to content

Commit c05ef93

Browse files
authored
Validate redirect locations (#14706)
1 parent c89c32c commit c05ef93

File tree

2 files changed

+35
-0
lines changed

2 files changed

+35
-0
lines changed

.changeset/hungry-pears-battle.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"react-router": patch
3+
---
4+
5+
Validate redirect locations

packages/react-router/lib/router/router.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1993,6 +1993,7 @@ export function createRouter(init: RouterInit): Router {
19931993
result.response.headers.get("Location")!,
19941994
new URL(request.url),
19951995
basename,
1996+
init.history,
19961997
);
19971998
replace = location === state.location.pathname + state.location.search;
19981999
}
@@ -2911,6 +2912,7 @@ export function createRouter(init: RouterInit): Router {
29112912
location,
29122913
new URL(request.url),
29132914
basename,
2915+
init.history,
29142916
);
29152917
let redirectLocation = createLocation(state.location, location, {
29162918
_isRedirect: true,
@@ -6396,18 +6398,46 @@ function normalizeRedirectLocation(
63966398
location: string,
63976399
currentUrl: URL,
63986400
basename: string,
6401+
historyInstance: History,
63996402
): string {
6403+
// Match Chrome's behavior:
6404+
// https://github.com/chromium/chromium/blob/216dbeb61db0c667e62082e5f5400a32d6983df3/content/public/common/url_utils.cc#L82
6405+
let invalidProtocols = [
6406+
"about:",
6407+
"blob:",
6408+
"chrome:",
6409+
"chrome-untrusted:",
6410+
"content:",
6411+
"data:",
6412+
"devtools:",
6413+
"file:",
6414+
"filesystem:",
6415+
// eslint-disable-next-line no-script-url
6416+
"javascript:",
6417+
];
6418+
64006419
if (isAbsoluteUrl(location)) {
64016420
// Strip off the protocol+origin for same-origin + same-basename absolute redirects
64026421
let normalizedLocation = location;
64036422
let url = normalizedLocation.startsWith("//")
64046423
? new URL(currentUrl.protocol + normalizedLocation)
64056424
: new URL(normalizedLocation);
6425+
if (invalidProtocols.includes(url.protocol)) {
6426+
throw new Error("Invalid redirect location");
6427+
}
64066428
let isSameBasename = stripBasename(url.pathname, basename) != null;
64076429
if (url.origin === currentUrl.origin && isSameBasename) {
64086430
return url.pathname + url.search + url.hash;
64096431
}
64106432
}
6433+
6434+
try {
6435+
let url = historyInstance.createURL(location);
6436+
if (invalidProtocols.includes(url.protocol)) {
6437+
throw new Error("Invalid redirect location");
6438+
}
6439+
} catch (e) {}
6440+
64116441
return location;
64126442
}
64136443

0 commit comments

Comments
 (0)