security: harden web server, daemon socket, and write paths #9

Merged
Pakobbix merged 1 commits from security/hardening into main 2026-09-10 14:20:58 +00:00
Collaborator

Security review for production deployment on a shared AI server. All findings fixed and covered by regression tests.

Critical

  • Unauthenticated arbitrary file read: the SPA catch-all joined the raw URL path onto the dist dir without containment — GET /%2e%2e/.../etc/passwd leaked any file readable by the root server. Now realpath-contained, fail-closed 404.

High

  • Daemon socket: serve_start no longer accepts caller-chosen host/port (socket is world-connectable; callers could rebind the root server to 0.0.0.0). Daemon always binds the configured address; CLI warns on mismatch.

Medium

  • Removed per-request max_delta_khz API override — the server-enforced safety cap is authoritative. CLI direct paths (write, profile apply, verify) honor the configured cap; --max-delta still overrides for explicit root use.
  • Snapshot restore confined to the snapshot dir (realpath, blocks symlink escapes).
  • New trusted_proxies config: X-Forwarded-For honored only for listed peers (rightmost untrusted hop), so the login lockout works behind a reverse proxy; spoofed headers ignored.
  • New allow_api_shutdown config (default true) to disable POST /api/shutdown on shared systems.

TLS (opt-in, like auth)

  • ssl_certfile/ssl_keyfile config + CLI flags (serve start, service install/configure, --no-ssl). When active: HTTPS UI/API, wss:// WebSockets, Secure session cookie, CLI auto-https. Cert/key validated up front.

Tests & docs

  • tests/test_security.py: standalone regression tests (no new deps) — 26/26 passing.
  • README + Usage-Guide: TLS section, new config keys, updated security notes.

Behavior changes: API clients sending max_delta_khz are silently ignored; snapshot restore --file is confined to the snapshot dir on the root CLI path too.

Security review for production deployment on a shared AI server. All findings fixed and covered by regression tests. **Critical** - Unauthenticated arbitrary file read: the SPA catch-all joined the raw URL path onto the dist dir without containment — `GET /%2e%2e/.../etc/passwd` leaked any file readable by the root server. Now realpath-contained, fail-closed 404. **High** - Daemon socket: `serve_start` no longer accepts caller-chosen host/port (socket is world-connectable; callers could rebind the root server to 0.0.0.0). Daemon always binds the configured address; CLI warns on mismatch. **Medium** - Removed per-request `max_delta_khz` API override — the server-enforced safety cap is authoritative. CLI direct paths (write, profile apply, verify) honor the configured cap; `--max-delta` still overrides for explicit root use. - Snapshot restore confined to the snapshot dir (realpath, blocks symlink escapes). - New `trusted_proxies` config: `X-Forwarded-For` honored only for listed peers (rightmost untrusted hop), so the login lockout works behind a reverse proxy; spoofed headers ignored. - New `allow_api_shutdown` config (default true) to disable `POST /api/shutdown` on shared systems. **TLS (opt-in, like auth)** - `ssl_certfile`/`ssl_keyfile` config + CLI flags (`serve start`, `service install/configure`, `--no-ssl`). When active: HTTPS UI/API, `wss://` WebSockets, `Secure` session cookie, CLI auto-https. Cert/key validated up front. **Tests & docs** - `tests/test_security.py`: standalone regression tests (no new deps) — 26/26 passing. - README + Usage-Guide: TLS section, new config keys, updated security notes. Behavior changes: API clients sending `max_delta_khz` are silently ignored; `snapshot restore --file` is confined to the snapshot dir on the root CLI path too.
ARIA added 1 commit 2026-09-10 14:20:25 +00:00
Security review findings, fixed and verified:

Critical
- Fix unauthenticated arbitrary file read: the SPA catch-all route
  joined the raw URL path onto the dist dir without containment, so
  encoded '..' segments (/%2e%2e/etc/passwd) leaked any file readable
  by the root server. Resolve with realpath and reject paths outside
  the dist dir (fail-closed 404).

High
- Daemon socket: serve_start no longer accepts caller-chosen
  host/port. The socket is world-connectable (unprivileged CLI users),
  so callers could previously rebind the root web server to 0.0.0.0.
  The daemon now always binds the operator-configured address and
  reports it in the response; the CLI warns on mismatch.

Medium
- Remove the per-request max_delta_khz override from the API: the
  server-enforced safety cap is now authoritative. CLI direct paths
  (write, profile apply, verify) honor the configured cap; --max-delta
  still overrides for explicit root use.
- Snapshot restore: confine filepath to the snapshot directory
  (realpath containment; blocks symlink escapes).
- Login lockout: honor X-Forwarded-For only for peers listed in the
  new trusted_proxies config (rightmost untrusted hop), so the
  per-IP lockout works behind a reverse proxy. Spoofed headers from
  untrusted peers are ignored.
- /api/shutdown: new allow_api_shutdown config (default true);
  shared systems can disable the API shutdown path.

TLS (opt-in, like auth)
- New ssl_certfile/ssl_keyfile config + CLI flags (serve start,
  service install/configure, --no-ssl to disable). When active:
  HTTPS for UI/API, wss:// for WebSockets, Secure session cookie,
  CLI auto-switches to https://. Cert/key paths are validated up
  front with a clear error instead of a silent uvicorn crash.

Tests & docs
- tests/test_security.py: standalone regression tests (no new deps)
  covering SPA containment, snapshot containment, cap removal,
  client-IP derivation, proxy normalization, TLS scheme detection,
  and daemon host/port hardening.
- README + Usage-Guide: TLS section, new config keys, updated
  security notes.
Collaborator

✅ No issues found — changes look consistent with the stated intent. Ready to be merged.

✅ No issues found — changes look consistent with the stated intent. Ready to be merged.
Pakobbix merged commit d810c44478 into main 2026-09-10 14:20:58 +00:00
Pakobbix deleted branch security/hardening 2026-09-10 14:20:58 +00:00
Sign in to join this conversation.