security: fix critical vulnerabilities and code quality issues

Critical fixes:
- init_admin.py: replace hardcoded admin123 password with ADMIN_PASSWORD env var
- proxmox_client.py, models.py: change verify_ssl default from False to True
- api/proxmox.py: use server.verify_ssl instead of hardcoded verify=False in websocket handler
- ssh_client.py: replace AutoAddPolicy (MITM-vulnerable) with WarningPolicy + load_system_host_keys

Security hardening:
- main.py: add security headers middleware (CSP, X-Frame-Options, HSTS, X-XSS-Protection, Referrer-Policy)
- main.py: fix CORS — allow_credentials=True is incompatible with allow_origins=["*"]; read origins from CORS_ORIGINS env var
- auth.py, logging_middleware.py: validate X-Forwarded-For/X-Real-IP to prevent IP spoofing

Performance:
- monitoring_worker.py: wire up cleanup_expired_connections() as hourly scheduled job (was defined but never called)

Code quality:
- logging_service.py: move `import json` from inside function to module level
- ssh_client.py, proxmox_client.py, api/proxmox.py, rbac/migration.py, task_queue_service.py: replace all bare `except:` with `except Exception:`
- .env.example, config.py: document ADMIN_PASSWORD and CORS_ORIGINS settings

https://claude.ai/code/session_019rK2wvaWg5zXFwmAPPEB7R
This commit is contained in:
Claude
2026-03-06 15:57:20 +00:00
parent e6facf43f4
commit 91ff467f2f
14 changed files with 122 additions and 53 deletions

View File

@@ -163,24 +163,47 @@ def create_app() -> FastAPI:
)
# Add CORS middleware
cors_origins = [o.strip() for o in settings.CORS_ORIGINS.split(",") if o.strip()]
# allow_credentials=True is incompatible with allow_origins=["*"] per the CORS spec.
# Disable credentials when wildcard origin is configured.
allow_credentials = cors_origins != ["*"]
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # In production, specify exact origins
allow_credentials=True,
allow_origins=cors_origins,
allow_credentials=allow_credentials,
allow_methods=["*"],
allow_headers=["*"],
)
# Add request logging middleware
app.add_middleware(RequestLoggingMiddleware, enable_api_logging=True)
# Add language detection middleware
app.add_middleware(LanguageMiddleware)
# Templates
templates = Jinja2Templates(directory="app/templates")
# Security headers middleware
@app.middleware("http")
async def add_security_headers(request: Request, call_next):
response = await call_next(request)
response.headers["X-Content-Type-Options"] = "nosniff"
response.headers["X-Frame-Options"] = "SAMEORIGIN"
response.headers["X-XSS-Protection"] = "1; mode=block"
response.headers["Referrer-Policy"] = "strict-origin-when-cross-origin"
response.headers["Content-Security-Policy"] = (
"default-src 'self'; "
"script-src 'self' 'unsafe-inline' 'unsafe-eval'; "
"style-src 'self' 'unsafe-inline'; "
"img-src 'self' data: blob:; "
"connect-src 'self' wss: ws:; "
"font-src 'self' data:; "
"frame-ancestors 'self';"
)
if not settings.DEBUG:
response.headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains"
return response
# Custom exception handler
@app.exception_handler(Exception)