From 4f7274d50b1e9cfdc449174a561cd007b50eaeed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89mile=20R=C3=A9?= Date: Wed, 11 Feb 2026 22:34:04 +0400 Subject: [PATCH] Use safe redirections MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Émile Ré --- .../iam/auth/sign-in/PasswordSignInPage.tsx | 16 +++++++++++++++- .../pages/iam/organizations/AssumePage.tsx | 19 +++++++++++++------ 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/apps/console/src/pages/iam/auth/sign-in/PasswordSignInPage.tsx b/apps/console/src/pages/iam/auth/sign-in/PasswordSignInPage.tsx index 0736f845c..ee561f996 100644 --- a/apps/console/src/pages/iam/auth/sign-in/PasswordSignInPage.tsx +++ b/apps/console/src/pages/iam/auth/sign-in/PasswordSignInPage.tsx @@ -36,6 +36,20 @@ export default function PasswordSignInPage() { if (!emailValue || !passwordValue) return; + const continueUrlParam = searchParams.get("continue"); + let safeContinueUrl: string; + if (continueUrlParam) { + let continueUrl: URL; + try { + continueUrl = new URL(continueUrlParam, window.location.origin); + } catch { + continueUrl = new URL(window.location.origin); + } + safeContinueUrl = window.location.origin + continueUrl.pathname + continueUrl.search; + } else { + safeContinueUrl = window.location.origin; + } + signIn({ variables: { input: { @@ -59,7 +73,7 @@ export default function PasswordSignInPage() { return; } - window.location.href = searchParams.get("continue") ?? window.location.origin; + window.location.href = safeContinueUrl; }, onError: (e) => { toast({ diff --git a/apps/console/src/pages/iam/organizations/AssumePage.tsx b/apps/console/src/pages/iam/organizations/AssumePage.tsx index 35e772116..7ae837a85 100644 --- a/apps/console/src/pages/iam/organizations/AssumePage.tsx +++ b/apps/console/src/pages/iam/organizations/AssumePage.tsx @@ -38,18 +38,25 @@ function AssumePageInner() { const [assumeOrganizationSession] = useMutation(assumeMutation); - const continueUrl = searchParams.get("continue") ?? new URL(`/organizations/${organizationId}`, window.location.origin).toString(); + const continueUrlParam = searchParams.get("continue"); + let safeContinueUrl: string; + if (continueUrlParam) { + const continueUrl = new URL(continueUrlParam); + safeContinueUrl = window.location.origin + continueUrl.pathname + continueUrl.search; + } else { + safeContinueUrl = window.location.origin + `/organizations/${organizationId}`; + } useEffect(() => { assumeOrganizationSession({ variables: { - input: { organizationId, continue: continueUrl }, + input: { organizationId, continue: safeContinueUrl }, }, onError: (error) => { if (error instanceof UnAuthenticatedError) { const search = new URLSearchParams([ ["organization-id", organizationId], - ["continue", continueUrl], + ["continue", safeContinueUrl], ]); void navigate({ pathname: "/auth/login", search: "?" + search.toString() }); @@ -68,7 +75,7 @@ function AssumePageInner() { switch (result.__typename) { case "PasswordRequired": search.set("organization-id", organizationId); - search.set("continue", continueUrl); + search.set("continue", safeContinueUrl); void navigate({ pathname: "/auth/password-login", search: "?" + search.toString() }); break; @@ -79,11 +86,11 @@ function AssumePageInner() { window.location.href = samlSSOLoginURL.toString(); break; default: - window.location.href = continueUrl; + window.location.href = safeContinueUrl; } }, }); - }, [organizationId, navigate, assumeOrganizationSession, continueUrl, searchParams]); + }, [organizationId, navigate, assumeOrganizationSession, safeContinueUrl, searchParams]); return (