diff --git a/apps/web/app/(use-page-wrapper)/auth/setup/page.tsx b/apps/web/app/(use-page-wrapper)/auth/setup/page.tsx index b67456a421..2fadd6c1e6 100644 --- a/apps/web/app/(use-page-wrapper)/auth/setup/page.tsx +++ b/apps/web/app/(use-page-wrapper)/auth/setup/page.tsx @@ -2,6 +2,8 @@ import { withAppDirSsr } from "app/WithAppDirSsr"; import type { PageProps as ServerPageProps } from "app/_types"; import { _generateMetadata } from "app/_utils"; import { cookies, headers } from "next/headers"; +import { redirect } from "next/navigation"; +import { z } from "zod"; import { buildLegacyCtx } from "@lib/buildLegacyCtx"; @@ -21,11 +23,18 @@ export const generateMetadata = async () => { }; const getData = withAppDirSsr(getServerSideProps); +const stepSchema = z.enum(["1", "2", "3", "4"]); -const ServerPage = async ({ params, searchParams }: ServerPageProps) => { - const props = await getData( - buildLegacyCtx(await headers(), await cookies(), await params, await searchParams) - ); +const ServerPage = async ({ params, searchParams: _searchParams }: ServerPageProps) => { + const searchParams = await _searchParams; + const stepResult = stepSchema.safeParse(searchParams?.step); + + // If step parameter is invalid, redirect to step 1 + if (!stepResult.success) { + return redirect(`/auth/setup?step=1`); + } + + const props = await getData(buildLegacyCtx(await headers(), await cookies(), await params, searchParams)); return ; }; diff --git a/packages/ui/components/form/wizard/WizardForm.tsx b/packages/ui/components/form/wizard/WizardForm.tsx index 434ae7e7a3..3c17f5e0bb 100644 --- a/packages/ui/components/form/wizard/WizardForm.tsx +++ b/packages/ui/components/form/wizard/WizardForm.tsx @@ -5,6 +5,7 @@ import { noop } from "lodash"; import { useRouter } from "next/navigation"; import type { Dispatch, SetStateAction } from "react"; import { useEffect, useState } from "react"; +import { z } from "zod"; import { useCompatSearchParams } from "@calcom/lib/hooks/useCompatSearchParams"; import classNames from "@calcom/ui/classNames"; @@ -35,7 +36,9 @@ function WizardForm(props: { const searchParams = useCompatSearchParams(); const { href, steps, nextLabel = "Next", finishLabel = "Finish", prevLabel = "Back", stepLabel } = props; const router = useRouter(); - const step = parseInt((searchParams?.get("step") as string) || "1"); + const stepSchema = z.coerce.number().int().min(1).max(steps.length).default(1); + const stepResult = stepSchema.safeParse(searchParams?.get("step")); + const step = stepResult.success ? stepResult.data : 1; const currentStep = steps[step - 1]; const setStep = (newStep: number) => { router.replace(`${href}?step=${newStep || 1}`);