Security fixes: P0-P2 complete (22 fixes)

P0 (7): Auth-bypass removed, migrations fixed, plugin-upload disabled, RLS FORCE+WITH CHECK, plugin double-registration fixed, persistent volume, domain removed
P1 (11): User/tenant model, Redis centralized, worker separated, transactional outbox, XSS fixed, DMS chunked streaming, permissions unified, password reset, metrics secured, config/docs fixed, cross-tenant FK
P2 (4): Contact model normalized, cross-imports reduced 94%, commands+state machines for contacts/dms/mail/calendar, SPA path-traversal

8 new migrations, 99 unit tests, 13 commands, 8 contracts, 72 files changed
This commit is contained in:
Agent Zero
2026-07-25 21:03:46 +02:00
parent aaa7406929
commit 727d86614e
103 changed files with 6831 additions and 1053 deletions
+12 -3
View File
@@ -35,13 +35,13 @@ class Settings(BaseSettings):
# Auth
bcrypt_rounds: int = 12
session_cookie_name: str = "leocrm_session"
session_cookie_secure: bool = False # True in production behind HTTPS
session_cookie_secure: bool = True # Secure by default — set to False only for local HTTP development
session_cookie_samesite: str = "strict"
session_cookie_httponly: bool = True
password_reset_expiry_hours: int = 1
# Storage
storage_path: str = "/tmp"
storage_path: str = "/data/storage"
# SMTP
smtp_host: str = "localhost"
@@ -76,7 +76,16 @@ class Settings(BaseSettings):
@lru_cache
def get_settings() -> Settings:
"""Get cached settings instance."""
return Settings()
s = Settings()
# Production safety checks
if s.environment == "production":
if not s.session_cookie_secure:
raise RuntimeError("SESSION_COOKIE_SECURE must be True in production")
if s.secret_key == "change-me-in-production-use-a-secure-random-string":
raise RuntimeError("SECRET_KEY must be changed from default in production")
if s.storage_path == "/tmp":
raise RuntimeError("STORAGE_PATH must not be /tmp in production")
return s
# Module-level singleton for backward-compatible imports