diff options
| author | kj_sh604 | 2026-04-03 02:09:14 -0400 |
|---|---|---|
| committer | kj_sh604 | 2026-04-03 02:09:14 -0400 |
| commit | d6458885e00788e1dec779b6807a79646aac6ed6 (patch) | |
| tree | 242f105571de42ab2a0a810ca79d41de5921d20c /auth_backend.py | |
| parent | 90ba16a3b4d1dfc29a614522824d87c5cae14bf8 (diff) | |
refactor: xss and sql injection security hardening
Diffstat (limited to 'auth_backend.py')
| -rw-r--r-- | auth_backend.py | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/auth_backend.py b/auth_backend.py index a8ad782..3902d1e 100644 --- a/auth_backend.py +++ b/auth_backend.py @@ -14,6 +14,9 @@ from typing import Callable, Optional, Protocol # we store encrypted challenge output instead of storing passwords. AUTH_CHALLENGE = "SHIM_AUTH_VALID" USERNAME_RE = re.compile(r"^[a-z0-9_.-]{2,64}$") +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}$" +) ConnectFn = Callable[[], sqlite3.Connection] @@ -39,6 +42,13 @@ def normalize_username(username: str) -> str: return username.strip().lower() +def normalize_uuid(value: str) -> Optional[str]: + candidate = (value or "").strip().lower() + if not UUID_RE.fullmatch(candidate): + return None + return candidate + + def looks_like_python_script(path: Path) -> bool: try: with open(path, "r", encoding="utf-8", errors="ignore") as f: @@ -93,6 +103,10 @@ class LocalMojicryptAuthBackend: return False, "username already exists" def update_username(self, user_uuid: str, new_username: str) -> tuple[bool, str]: + normalized_user_uuid = normalize_uuid(user_uuid) + if normalized_user_uuid is None: + return False, "invalid user id" + normalized = normalize_username(new_username) username_error = self._validate_username(normalized) if username_error: @@ -102,7 +116,7 @@ class LocalMojicryptAuthBackend: with self.connect_db() as conn: cursor = conn.execute( "UPDATE users SET username = ? WHERE user_uuid = ?", - (normalized, user_uuid), + (normalized, normalized_user_uuid), ) if cursor.rowcount == 0: return False, "user not found" @@ -112,6 +126,10 @@ class LocalMojicryptAuthBackend: return True, "username updated" def update_password(self, user_uuid: str, new_password: str) -> tuple[bool, str]: + normalized_user_uuid = normalize_uuid(user_uuid) + if normalized_user_uuid is None: + return False, "invalid user id" + password_error = self._validate_password(new_password) if password_error: return False, password_error @@ -124,7 +142,7 @@ class LocalMojicryptAuthBackend: with self.connect_db() as conn: cursor = conn.execute( "UPDATE users SET encrypted_challenge = ? WHERE user_uuid = ?", - (encrypted, user_uuid), + (encrypted, normalized_user_uuid), ) if cursor.rowcount == 0: return False, "user not found" |
