A form that validates only in the browser
Don't
const [form, fields] = useForm({
onValidate: ({ formData }) => parseWithValibot(formData, { schema }),
})
export async function action({ request }: Route.ActionArgs) {
const formData = await request.formData()
// The schema never runs here. A POST from anywhere but this form is unchecked.
await createUser({ email: String(formData.get("email")) })
return redirect("/welcome")
}Do
// app/schemas/signup.ts — one module, imported by both sides
export const signupSchema = v.object({
email: v.pipe(v.string(), v.email("Enter a valid email address")),
})
// app/routes/signup.tsx
export async function action({ request }: Route.ActionArgs) {
const submission = parseWithValibot(await request.formData(), { schema: signupSchema })
if (submission.status !== "success") return submission.reply()
await createUser(submission.value)
return redirect("/welcome")
}submission.value is typed and parsed, so the String(formData.get(...)) casts disappear along with the vulnerability.