fix(security): add username validation, constant-time login, default credential rejection, and tooling

This commit is contained in:
2026-02-18 19:11:14 +01:00
parent 1521005b62
commit f41b8fd8c2
8 changed files with 393 additions and 1 deletions

View File

@@ -7,6 +7,27 @@ from datetime import datetime
from pydantic import BaseModel, ConfigDict, EmailStr, field_validator
# ── Username policy ─────────────────────────────────────────────────
_USERNAME_RE = re.compile(r"^[a-zA-Z0-9_-]{3,50}$")
_RESERVED_USERNAMES = frozenset({
"admin", "root", "system", "api", "null", "undefined",
"administrator", "superuser", "aegis",
})
def _validate_username(username: str) -> str:
"""Validate username format and reject reserved names."""
if not _USERNAME_RE.match(username):
raise ValueError(
"Username must be 3-50 characters, containing only "
"letters, digits, underscores, and hyphens"
)
if username.lower() in _RESERVED_USERNAMES:
raise ValueError(f"Username '{username}' is reserved")
return username
# ── Password policy ─────────────────────────────────────────────────
_MIN_PASSWORD_LENGTH = 12
@@ -56,6 +77,11 @@ class UserCreate(BaseModel):
password: str
role: str = "viewer"
@field_validator("username")
@classmethod
def username_format(cls, v: str) -> str:
return _validate_username(v)
@field_validator("password")
@classmethod
def password_strength(cls, v: str) -> str: