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

@@ -46,7 +46,7 @@ class SSHClient:
transport = client.get_transport()
if transport and transport.is_active():
return client
except:
except Exception:
pass
# Remove invalid connection
@@ -64,7 +64,7 @@ class SSHClient:
if self.connection_key in self._connections:
try:
self._connections[self.connection_key].close()
except:
except Exception:
pass
del self._connections[self.connection_key]
del self._connection_times[self.connection_key]
@@ -82,7 +82,8 @@ class SSHClient:
for attempt in range(self.max_retries):
try:
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.WarningPolicy())
connect_kwargs = {
'hostname': self.hostname,
@@ -169,7 +170,7 @@ class SSHClient:
try:
transport = self.client.get_transport()
return transport and transport.is_active()
except:
except Exception:
return False
def close(self):
@@ -235,7 +236,7 @@ class SSHClient:
for key in list(cls._connections.keys()):
try:
cls._connections[key].close()
except:
except Exception:
pass
cls._connections.clear()
cls._connection_times.clear()
@@ -409,7 +410,7 @@ async def cleanup_ssh_connections():
if key in SSHClient._connections:
try:
SSHClient._connections[key].close()
except:
except Exception:
pass
del SSHClient._connections[key]
del SSHClient._connection_times[key]