From 939dfddb93054673172ca7a25f601806f6bad38a Mon Sep 17 00:00:00 2001 From: root Date: Thu, 30 Apr 2026 03:14:08 -0500 Subject: [PATCH] llm_team_ui: 4 fixes from 2026-04-30 cross-lineage scrum MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cross-lineage scrum (Opus 4.7 + Kimi K2.6 + Qwen3-coder via the local-review-harness chatd) on this codebase surfaced 5 BLOCK-class issues from Opus + a convergent finding from the harness. This commit lands the 4 surgical fixes; OB-3 (web app runs as root with fail2ban-client + systemctl reload nginx + writes to /etc/nginx/banned_ips.conf) needs an architectural split into a non-root web tier + a privileged sudo wrapper, deferred for its own session. OB-1 — log file open at import crashes app on perm error Pre-fix: `_sec_handler = logging.FileHandler("/var/log/llm-team- security.log")` raised PermissionError at import time on any non-root or fresh-install run, killing the app before Flask started — failure was silent (no Flask process to inspect logs on). Fix: try/except, fall back to StreamHandler(sys.stderr) when the path is unwritable. App starts; sec_log events still land in journald via stderr. LLM_TEAM_SECURITY_LOG env var lets operators override the path. OB-2 — DB password hardcoded in source (CONVERGENT FINDING) The `kbuser` Postgres credential `IPbLBA0EQI8u4TeM2YZrbm1OAy5nSwqC` was leaked in source here AND in voice-ai/audiosocket_bridge.py + voice-ai/sales_assistant.py. Caught independently by harness LLM phase (qwen3.5 local) on voice-ai earlier today AND Opus on this file just now. Same password, same DB (`knowledge_base`) shared between services, three reviewers converged. Fix: source from LLM_TEAM_DB_DSN env var, fail loud on unset. Operator follow-ups: 1. Rotate the password in Postgres (still in git history; redacting source doesn't un-leak it). 2. Set LLM_TEAM_DB_DSN in /etc/llm-team-ui.env (mode 0600, loaded via systemd EnvironmentFile=). 3. Same DSN env-var pattern needs applying to voice-ai/audiosocket_bridge.py:47 once that branch's workspace_context WIP lands. OB-5 — demo_mode default=True ships public access on first boot Pre-fix: `_demo_mode = {"active": True, ...}` + the demo branch in login_required let users through without a session. Combined with /api/run + /api/imagegen proxies, fresh installs were open LLM/compute abuse surface from first boot. Fix: default to False; LLM_TEAM_DEMO_MODE=1 env override exists for the public devop.live deployment systemd unit so the demo doesn't need a manual flip on every restart, but everywhere else defaults closed. OB-4 — EXPLOIT_PATTERNS LAN/admin lockout Pre-fix: regex matched on `request.path` + query string against patterns like UNION / SELECT / ;-- /