Skip to content

Commit 5faeac6

Browse files
baozhoutaoclaude
andauthored
fix(auth): spell isLikelyEmail ASCII range with printable bounds (no control char) (#3613)
Mirror the objectui hygiene fix: `[^\x20-\x7e]` instead of `[^\x00-\x7f]` so the regex literal carries no control character (eslint no-control-regex). Same semantics — anything outside printable ASCII fails the email pre-filter. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent b0e78a8 commit 5faeac6

2 files changed

Lines changed: 19 additions & 6 deletions

File tree

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
"@objectstack/plugin-auth": patch
3+
---
4+
5+
fix(auth): spell isLikelyEmail's ASCII guard with printable bounds (no control char)
6+
7+
The non-ASCII guard added in framework#3566 was written as `[^\x00-\x7f]`, whose
8+
regex literal embeds a control character (`\x00`). Rewrite it as `[^\x20-\x7e]`
9+
identical behaviour (anything outside printable ASCII fails the email
10+
pre-filter), but the pattern no longer carries a control character (eslint
11+
`no-control-regex`), and it matches the objectui side's `isPlausibleEmail`.

packages/plugins/plugin-auth/src/admin-user-endpoints.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -187,12 +187,14 @@ function badRequest(message: string): EndpointResult {
187187
*/
188188
export function isLikelyEmail(value: string): boolean {
189189
if (value.length === 0 || value.length > 254 || /\s/.test(value)) return false;
190-
// Reject non-ASCII up front so obviously-invalid addresses (e.g. a Chinese
191-
// domain like `x@柴仟.com`) fail this pre-filter — and therefore the import
192-
// dry-run — instead of passing here only to be rejected later by
193-
// better-auth's strict ASCII validator at real-import time (framework#3566).
194-
// A single linear char-class test; no backtracking (see the ReDoS note above).
195-
if (/[^\x00-\x7f]/.test(value)) return false;
190+
// Reject anything outside printable ASCII up front so obviously-invalid
191+
// addresses (e.g. a Chinese domain like `x@柴仟.com`) fail this pre-filter —
192+
// and therefore the import dry-run — instead of passing here only to be
193+
// rejected later by better-auth's strict ASCII validator at real-import time
194+
// (framework#3566). A single linear char-class test; no backtracking (see the
195+
// ReDoS note above). The range is spelled with printable bounds (0x20–0x7e)
196+
// so the pattern itself carries no control character (eslint no-control-regex).
197+
if (/[^\x20-\x7e]/.test(value)) return false;
196198
const at = value.indexOf('@');
197199
if (at <= 0 || at !== value.lastIndexOf('@') || at === value.length - 1) return false;
198200
const domain = value.slice(at + 1);

0 commit comments

Comments
 (0)