security: harden dashboard (SSH keys, auth, uploads, CORS, non-root)

Remove SSH private keys from git, add SECRET_KEY validation, move WS
auth from query string to first message, add session limits/idle timeout,
PBKDF2 Fernet key, refresh token rotation, TOTP replay protection,
file upload size limit + filename sanitization, symlink safety check,
restrict CORS methods, IP-gate OpenClaw token, run container as non-root,
rate-limit refresh/passkey endpoints, sanitize Gitea path params.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Gan, Jimmy
2026-02-26 17:22:25 +08:00
parent d25b3f0785
commit 394a1aa367
15 changed files with 164 additions and 31 deletions
+3
View File
@@ -8,6 +8,8 @@ VOLUME_ROOT = os.environ.get("VOLUME_ROOT", "/volume1")
# Auth
SECRET_KEY = os.environ.get("SECRET_KEY", "")
if not SECRET_KEY or len(SECRET_KEY) < 32:
raise RuntimeError("SECRET_KEY must be set and at least 32 characters")
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
REFRESH_TOKEN_EXPIRE_MINUTES = 60 * 24 * 7 # 7 days
@@ -19,6 +21,7 @@ TOTP_SECRET = os.environ.get("TOTP_SECRET", "")
SSH_HOST = os.environ.get("SSH_HOST", "host.docker.internal")
SSH_USER = os.environ.get("SSH_USER", "zjgump")
SSH_KEY_PATH = os.environ.get("SSH_KEY_PATH", "/app/ssh/id_ed25519")
SSH_KNOWN_HOSTS = os.environ.get("SSH_KNOWN_HOSTS", "/app/ssh/known_hosts")
VPS_SSH_HOST = os.environ.get("VPS_SSH_HOST", "158.101.140.85")
VPS_SSH_USER = os.environ.get("VPS_SSH_USER", "jimmyg")