Skip to content

Commit

Permalink
fix(clerk-js): Update isAllowedRedirectOrigin to handle malformed or …
Browse files Browse the repository at this point in the history
…protocol-relative URLs (#4317)
  • Loading branch information
nikosdouvlis authored and izaaklauer committed Oct 17, 2024
1 parent f3c80e8 commit 000f773
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 20 deletions.
5 changes: 5 additions & 0 deletions .changeset/blue-pumpkins-travel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@clerk/clerk-js": patch
---

Correctly handle malformed or protocol-relative URLs before navigating to cross-origin URLs
6 changes: 6 additions & 0 deletions packages/clerk-js/src/utils/__tests__/url.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,12 @@ describe('isAllowedRedirectOrigin', () => {
// regexp
['https://www.clerk.com/foo?hello=1', [/https:\/\/www\.clerk\.com/], true],
['https://test.clerk.com/foo?hello=1', [/https:\/\/www\.clerk\.com/], false],
// malformed or protocol-relative URLs
['http:evil.com', [/https:\/\/www\.clerk\.com/], false],
['https:evil.com', [/https:\/\/www\.clerk\.com/], false],
['http//evil.com', [/https:\/\/www\.clerk\.com/], false],
['https//evil.com', [/https:\/\/www\.clerk\.com/], false],
['//evil.com', [/https:\/\/www\.clerk\.com/], false],
];

const warnMock = jest.spyOn(logger, 'warnOnce');
Expand Down
40 changes: 20 additions & 20 deletions packages/clerk-js/src/utils/url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,15 +241,29 @@ export function relativeToAbsoluteUrl(url: string, origin: string | URL): string
return new URL(url, origin).href;
}

export function isRelativeUrl(val: unknown): val is string {
export function isRelativeUrl(val: string): boolean {
if (val !== val && !val) {
return false;
}

if (val.startsWith('//') || val.startsWith('http/') || val.startsWith('https/')) {
// Protocol-relative URL; consider it absolute.
return false;
}

try {
const temp = new URL(val as string, DUMMY_URL_BASE);
return temp.origin === DUMMY_URL_BASE;
} catch (e) {
// If this does not throw, it's a valid absolute URL
new URL(val);
return false;
} catch (e) {
try {
// If this does not throw, it's a valid relative URL
new URL(val, DUMMY_URL_BASE);
return true;
} catch (e) {
// Invalid URL case
return false;
}
}
}

Expand Down Expand Up @@ -344,12 +358,11 @@ export const isAllowedRedirectOrigin =
return true;
}

const url = new URL(_url, DUMMY_URL_BASE);
const isRelativeUrl = url.origin === DUMMY_URL_BASE;
if (isRelativeUrl) {
if (isRelativeUrl(_url)) {
return true;
}

const url = new URL(_url, DUMMY_URL_BASE);
const isAllowed = allowedRedirectOrigins
.map(origin => (typeof origin === 'string' ? globs.toRegexp(trimTrailingSlash(origin)) : origin))
.some(origin => origin.test(trimTrailingSlash(url.origin)));
Expand Down Expand Up @@ -380,16 +393,3 @@ export function createAllowedRedirectOrigins(

return origins;
}

export const isCrossOrigin = (url: string | URL, origin: string | URL = window.location.origin): boolean => {
try {
if (isRelativeUrl(url)) {
return false;
}
const urlOrigin = new URL(url).origin;
const originOrigin = new URL(origin).origin;
return urlOrigin !== originOrigin;
} catch (e) {
return false;
}
};

0 comments on commit 000f773

Please sign in to comment.