diff --git a/web/hooks/use-oauth.ts b/web/hooks/use-oauth.ts index ae9c1cda66..9f21a476b3 100644 --- a/web/hooks/use-oauth.ts +++ b/web/hooks/use-oauth.ts @@ -1,5 +1,6 @@ 'use client' import { useEffect } from 'react' +import { validateRedirectUrl } from '@/utils/urlValidation' export const useOAuthCallback = () => { useEffect(() => { @@ -18,6 +19,7 @@ export const openOAuthPopup = (url: string, callback: () => void) => { const left = window.screenX + (window.outerWidth - width) / 2 const top = window.screenY + (window.outerHeight - height) / 2 + validateRedirectUrl(url) const popup = window.open( url, 'OAuth', diff --git a/web/utils/urlValidation.ts b/web/utils/urlValidation.ts new file mode 100644 index 0000000000..372dd54cb4 --- /dev/null +++ b/web/utils/urlValidation.ts @@ -0,0 +1,24 @@ +/** + * Validates that a URL is safe for redirection. + * Only allows HTTP and HTTPS protocols to prevent XSS attacks. + * + * @param url - The URL string to validate + * @throws Error if the URL has an unsafe protocol + */ +export function validateRedirectUrl(url: string): void { + try { + const parsedUrl = new URL(url); + if (parsedUrl.protocol !== "http:" && parsedUrl.protocol !== "https:") { + throw new Error("Authorization URL must be HTTP or HTTPS"); + } + } catch (error) { + if ( + error instanceof Error && + error.message === "Authorization URL must be HTTP or HTTPS" + ) { + throw error; + } + // If URL parsing fails, it's also invalid + throw new Error(`Invalid URL: ${url}`); + } +} \ No newline at end of file