From 97d55ccdc97ef7b0cc28ded5ebbb46c1879291ce Mon Sep 17 00:00:00 2001 From: kj_sh604 Date: Fri, 3 Apr 2026 02:42:36 -0400 Subject: refactor: better email validation --- auth_backend.py | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) (limited to 'auth_backend.py') diff --git a/auth_backend.py b/auth_backend.py index 00a5dbc..817f8d4 100644 --- a/auth_backend.py +++ b/auth_backend.py @@ -9,13 +9,13 @@ import uuid from pathlib import Path from typing import Callable, Optional, Protocol +from email_validator import EmailNotValidError, validate_email + # fixed challenge text used for passphrase verification. # we store encrypted challenge output instead of storing passwords. AUTH_CHALLENGE = "SHIM_AUTH_VALID" HANDLE_RE = re.compile(r"^[a-z0-9_.-]{2,64}$") -EMAIL_LOCAL_RE = re.compile(r"^[a-z0-9!#$%&'*+/=?^_`{|}~.-]{1,64}$") -EMAIL_DOMAIN_LABEL_RE = re.compile(r"^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$") UUID_RE = re.compile( r"^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$" ) @@ -54,25 +54,18 @@ def normalize_uuid(value: str) -> Optional[str]: def is_valid_email_username(value: str) -> bool: if len(value) > 254: return False - if "@" not in value or value.count("@") != 1: - return False - - local_part, domain = value.split("@", 1) - if not local_part or not domain: - return False - if local_part.startswith(".") or local_part.endswith(".") or ".." in local_part: - return False - if not EMAIL_LOCAL_RE.fullmatch(local_part): + try: + validated = validate_email( + value, + check_deliverability=False, + allow_smtputf8=False, + allow_display_name=False, + ) + except EmailNotValidError: return False - labels = domain.split(".") - if len(labels) < 2: - return False - if any(not label for label in labels): - return False - if len(labels[-1]) < 2: - return False - return all(EMAIL_DOMAIN_LABEL_RE.fullmatch(label) for label in labels) + # keep stored usernames predictable - only accept already normalized forms. + return validated.normalized == value def looks_like_python_script(path: Path) -> bool: -- cgit v1.2.3