Skip to content

Commit 2fbb84c

Browse files
authored
Validate redirect locations (v6) (#14707)
1 parent 023be0c commit 2fbb84c

File tree

3 files changed

+39
-4
lines changed

3 files changed

+39
-4
lines changed

.changeset/loud-ways-float.md

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

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@
105105
},
106106
"filesize": {
107107
"packages/router/dist/router.umd.min.js": {
108-
"none": "58.1 kB"
108+
"none": "58.2 kB"
109109
},
110110
"packages/react-router/dist/react-router.production.min.js": {
111111
"none": "16.52 kB"

packages/router/router.ts

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1783,7 +1783,8 @@ export function createRouter(init: RouterInit): Router {
17831783
let location = normalizeRedirectLocation(
17841784
result.response.headers.get("Location")!,
17851785
new URL(request.url),
1786-
basename
1786+
basename,
1787+
init.history,
17871788
);
17881789
replace = location === state.location.pathname + state.location.search;
17891790
}
@@ -2695,7 +2696,8 @@ export function createRouter(init: RouterInit): Router {
26952696
location = normalizeRedirectLocation(
26962697
location,
26972698
new URL(request.url),
2698-
basename
2699+
basename,
2700+
init.history,
26992701
);
27002702
let redirectLocation = createLocation(state.location, location, {
27012703
_isRedirect: true,
@@ -5154,19 +5156,47 @@ function normalizeRelativeRoutingRedirectResponse(
51545156
function normalizeRedirectLocation(
51555157
location: string,
51565158
currentUrl: URL,
5157-
basename: string
5159+
basename: string,
5160+
historyInstance: History,
51585161
): string {
5162+
// Match Chrome's behavior:
5163+
// https://github.com/chromium/chromium/blob/216dbeb61db0c667e62082e5f5400a32d6983df3/content/public/common/url_utils.cc#L82
5164+
let invalidProtocols = [
5165+
"about:",
5166+
"blob:",
5167+
"chrome:",
5168+
"chrome-untrusted:",
5169+
"content:",
5170+
"data:",
5171+
"devtools:",
5172+
"file:",
5173+
"filesystem:",
5174+
// eslint-disable-next-line no-script-url
5175+
"javascript:",
5176+
];
5177+
51595178
if (ABSOLUTE_URL_REGEX.test(location)) {
51605179
// Strip off the protocol+origin for same-origin + same-basename absolute redirects
51615180
let normalizedLocation = location;
51625181
let url = normalizedLocation.startsWith("//")
51635182
? new URL(currentUrl.protocol + normalizedLocation)
51645183
: new URL(normalizedLocation);
5184+
if (invalidProtocols.includes(url.protocol)) {
5185+
throw new Error("Invalid redirect location");
5186+
}
51655187
let isSameBasename = stripBasename(url.pathname, basename) != null;
51665188
if (url.origin === currentUrl.origin && isSameBasename) {
51675189
return url.pathname + url.search + url.hash;
51685190
}
51695191
}
5192+
5193+
try {
5194+
let url = historyInstance.createURL(location);
5195+
if (invalidProtocols.includes(url.protocol)) {
5196+
throw new Error("Invalid redirect location");
5197+
}
5198+
} catch (e) {}
5199+
51705200
return location;
51715201
}
51725202

0 commit comments

Comments
 (0)