security: harden dashboard (SSH keys, auth, uploads, CORS, non-root)
Deploy Dashboard / deploy (push) Successful in 3m37s

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 db037eeb5c
commit c7a0a53fe8
19 changed files with 164 additions and 47 deletions
+3 -3
View File
@@ -26,8 +26,8 @@ app.add_middleware(
CORSMiddleware,
allow_origins=CORS_ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
allow_methods=["GET", "POST", "DELETE", "OPTIONS"],
allow_headers=["Authorization", "Content-Type"],
)
@app.exception_handler(RateLimitExceeded)
@@ -118,7 +118,7 @@ async def health():
async def client_ip(request: Request):
ip = request.headers.get("x-forwarded-for", "").split(",")[0].strip() or request.client.host
lan = ip.startswith("192.168.31.") or (ip.startswith("100.") and _router_reachable())
return {"ip": ip, "lan": lan}
return {"lan": lan}
def _router_reachable():
import socket