# Security notes ## Threat model The plugin is for a **private LAN** DeepSeek Harness web UI. It assumes: - The host is not reachable from the public internet. - Attackers on the LAN should not get a shell-capable agent without the password. - The operator can always recover from `127.0.0.1`. ## Controls - Inbound allowlist uses `socket.remoteAddress`, not `Host` / `X-Forwarded-For`. - Presence of proxy headers is a deny, not a source of identity. - Password is scrypt (`N=16384,r=8,p=1`) with a random 16-byte salt. - Login is rate-limited (5 failures / 60s / IP). - Session cookie is `HttpOnly; SameSite=Strict; Max-Age` (default 7 days). Token hashes persist in `$DSH_HOME/lan-gate-sessions.json` so a process restart does not log everyone out. Changing the password still drops all sessions. - Login POST requires `Origin` to match `Host` when `Origin` is present. - `/api` WebSocket upgrades are refused without a valid session (unless loopback bypass). - `GET /dsh-lan-full/state` never returns `passwordHash`. - Changing the password drops all sessions. ## Known residual issues 1. **No TLS.** HTTP on a LAN can leak the password and cookie to a passive observer. SameSite cookies do not fix that. If you need confidentiality, put TLS in front *without* adding forwarding headers, or only use loopback + SSH tunnel. 2. **Loopback bypass.** Enabled by default so a locked-out operator can recover. Disable `loopbackBypassAuth` if untrusted local processes share the host. A logged-in session can run bash; API keys are the operator's responsibility. ## Reporting Open a GitHub issue on this repository. Do not include live passwords or API keys.