From 2ba00fe2377f4d53947a84b8cdb314a63bbd6dd4 Mon Sep 17 00:00:00 2001 From: Macs Dickinson Date: Tue, 3 Oct 2023 19:32:15 +0100 Subject: [PATCH] [2609] fix ReDoS vulnerability in email regex (#2824) --- deno/lib/README.md | 2 +- deno/lib/__tests__/string.test.ts | 1 + deno/lib/types.ts | 2 +- src/__tests__/string.test.ts | 1 + src/types.ts | 2 +- 5 files changed, 5 insertions(+), 3 deletions(-) diff --git a/deno/lib/README.md b/deno/lib/README.md index 78cf45e7b..e693bd099 100644 --- a/deno/lib/README.md +++ b/deno/lib/README.md @@ -1879,7 +1879,7 @@ You can create a Zod schema for any TypeScript type by using `z.custom()`. This ```ts const px = z.custom<`${number}px`>((val) => { - return /^\d+px$/.test(val as string); + return typeof val === "string" ? /^\d+px$/.test(val) : false; }); type px = z.infer; // `${number}px` diff --git a/deno/lib/__tests__/string.test.ts b/deno/lib/__tests__/string.test.ts index e067a1c81..6b74cf9f5 100644 --- a/deno/lib/__tests__/string.test.ts +++ b/deno/lib/__tests__/string.test.ts @@ -146,6 +146,7 @@ test("email validations", () => { `gbacher0@[IPv6:bc37:4d3f:5048:2e26:37cc:248e:df8e:2f7f:af]`, `invalid@[IPv6:5348:4ed3:5d38:67fb:e9b:acd2:c13:192.168.256.1]`, `test@.com`, + `aaaaaaaaaaaaaaalongemailthatcausesregexDoSvulnerability@test.c` ]; const emailSchema = z.string().email(); diff --git a/deno/lib/types.ts b/deno/lib/types.ts index 39325a9a9..f99cab48a 100644 --- a/deno/lib/types.ts +++ b/deno/lib/types.ts @@ -565,7 +565,7 @@ const uuidRegex = // const emailRegex = // /^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])$/i; const emailRegex = - /^([A-Z0-9_+-]+\.?)*[A-Z0-9_+-]@([A-Z0-9][A-Z0-9\-]*\.)+[A-Z]{2,}$/i; + /^(?!\.)(?!.*\.\.)([A-Z0-9_+-\.]*)[A-Z0-9_+-]@([A-Z0-9][A-Z0-9\-]*\.)+[A-Z]{2,}$/i; // const emailRegex = // /^[a-z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-z0-9-]+(?:\.[a-z0-9\-]+)*$/i; diff --git a/src/__tests__/string.test.ts b/src/__tests__/string.test.ts index b84f080fc..e546bc82a 100644 --- a/src/__tests__/string.test.ts +++ b/src/__tests__/string.test.ts @@ -145,6 +145,7 @@ test("email validations", () => { `gbacher0@[IPv6:bc37:4d3f:5048:2e26:37cc:248e:df8e:2f7f:af]`, `invalid@[IPv6:5348:4ed3:5d38:67fb:e9b:acd2:c13:192.168.256.1]`, `test@.com`, + `aaaaaaaaaaaaaaalongemailthatcausesregexDoSvulnerability@test.c` ]; const emailSchema = z.string().email(); diff --git a/src/types.ts b/src/types.ts index 51e188948..723f6f824 100644 --- a/src/types.ts +++ b/src/types.ts @@ -565,7 +565,7 @@ const uuidRegex = // const emailRegex = // /^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])$/i; const emailRegex = - /^([A-Z0-9_+-]+\.?)*[A-Z0-9_+-]@([A-Z0-9][A-Z0-9\-]*\.)+[A-Z]{2,}$/i; + /^(?!\.)(?!.*\.\.)([A-Z0-9_+-\.]*)[A-Z0-9_+-]@([A-Z0-9][A-Z0-9\-]*\.)+[A-Z]{2,}$/i; // const emailRegex = // /^[a-z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-z0-9-]+(?:\.[a-z0-9\-]+)*$/i;