Skip to content

Commit 7a14188

Browse files
authored
fix(webapp): limit account email address length (#4330)
## Summary Limits user account email addresses to 254 characters in profile settings and onboarding. Oversized values are rejected before the uniqueness lookup, and the form fields enforce the same limit in the browser. ## Fix Both email update flows use a shared bounded email schema. Basic validation completes before the uniqueness lookup runs.
1 parent a9815f7 commit 7a14188

4 files changed

Lines changed: 28 additions & 11 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
area: webapp
3+
type: fix
4+
---
5+
6+
Limit account settings email input to 254 characters.

apps/webapp/app/routes/account._index/route.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { useUser } from "~/hooks/useUser";
2222
import { redirectWithSuccessMessage } from "~/models/message.server";
2323
import { updateUser } from "~/models/user.server";
2424
import { requireUserId } from "~/services/session.server";
25+
import { emailSchema, MAX_EMAIL_LENGTH } from "~/utils/emailValidation";
2526
import { accountPath } from "~/utils/pathBuilder";
2627

2728
export const meta: MetaFunction = () => {
@@ -42,10 +43,8 @@ function createSchema(
4243
.string({ required_error: "You must enter a name" })
4344
.min(2, "Your name must be at least 2 characters long")
4445
.max(50),
45-
email: z
46-
.string()
47-
.email()
48-
.superRefine((email, ctx) => {
46+
email: emailSchema.pipe(
47+
z.string().superRefine((email, ctx) => {
4948
if (constraints.isEmailUnique === undefined) {
5049
//client-side validation skips this
5150
ctx.addIssue({
@@ -65,7 +64,8 @@ function createSchema(
6564
});
6665
});
6766
}
68-
}),
67+
})
68+
),
6969
marketingEmails: z.preprocess((value) => value === "on", z.boolean()),
7070
});
7171
}
@@ -177,6 +177,7 @@ export default function Page() {
177177
<div className="flex w-56 flex-none flex-col gap-1">
178178
<Input
179179
{...getInputProps(email, { type: "text" })}
180+
maxLength={MAX_EMAIL_LENGTH}
180181
placeholder="Your email"
181182
defaultValue={user?.email ?? ""}
182183
/>

apps/webapp/app/routes/confirm-basic-details.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import { useUser } from "~/hooks/useUser";
2727
import { redirectWithSuccessMessage } from "~/models/message.server";
2828
import { updateUser } from "~/models/user.server";
2929
import { requireUserId } from "~/services/session.server";
30+
import { emailSchema, MAX_EMAIL_LENGTH } from "~/utils/emailValidation";
3031
import { rootPath } from "~/utils/pathBuilder";
3132
import { getVercelInstallParams } from "~/v3/vercel";
3233

@@ -72,10 +73,8 @@ function createSchema(
7273
return z
7374
.object({
7475
name: z.string().min(3, "Your name must be at least 3 characters").max(50),
75-
email: z
76-
.string()
77-
.email()
78-
.superRefine((email, ctx) => {
76+
email: emailSchema.pipe(
77+
z.string().superRefine((email, ctx) => {
7978
if (constraints.isEmailUnique === undefined) {
8079
ctx.addIssue({
8180
code: z.ZodIssueCode.custom,
@@ -93,8 +92,9 @@ function createSchema(
9392
});
9493
});
9594
}
96-
}),
97-
confirmEmail: z.string(),
95+
})
96+
),
97+
confirmEmail: emailSchema,
9898
referralSource: z.string().optional(),
9999
referralSourceOther: z.string().optional(),
100100
role: z.string().optional(),
@@ -290,6 +290,7 @@ export default function Page() {
290290
</Label>
291291
<Input
292292
{...getInputProps(email, { type: "email" })}
293+
maxLength={MAX_EMAIL_LENGTH}
293294
defaultValue={enteredEmail}
294295
onChange={(e) => {
295296
setEnteredEmail(e.target.value);
@@ -306,6 +307,7 @@ export default function Page() {
306307
<Label htmlFor={confirmEmail.id}>Confirm email</Label>
307308
<Input
308309
{...getInputProps(confirmEmail, { type: "email" })}
310+
maxLength={MAX_EMAIL_LENGTH}
309311
placeholder="Your email, again"
310312
icon={EnvelopeIcon}
311313
spellCheck={false}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { z } from "zod";
2+
3+
export const MAX_EMAIL_LENGTH = 254;
4+
5+
export const emailSchema = z
6+
.string()
7+
.email()
8+
.max(MAX_EMAIL_LENGTH, `Email must be ${MAX_EMAIL_LENGTH} characters or fewer`);

0 commit comments

Comments
 (0)