root b09b73c409 llm_team_ui: ban-system defense in depth (extends OB-4)
The OB-4 fix at 939dfdd was incomplete. It bypassed the path-regex
EXPLOIT check for allowlisted-IP admins, but _track_violation is
called from THREE sites (exploit_scan, rate_limit, login_fail) and
only the exploit_scan path had the bypass. An admin who hit a rate
limit + had a session timeout + entered a wrong password within 60s
could still self-ban via the OTHER paths, ending up locked out
through the back door.

This commit adds 4 layers of defense in depth, each independently
sufficient to stop an allowlisted IP from being banned:

1. _track_violation: bail early if is_allowlisted(ip). Allowlisted
   IPs never accumulate violations from ANY path. Plus eviction
   sweep when _violation_tracker grows >10K (same shape as the
   _rate_limit eviction at 266de61).

2. _auto_escalate: re-check is_allowlisted before issuing any ban.
   Defense in depth — if a future call path bypasses #1, this
   catches it.

3. _nginx_ban: refuse to write the deny rule for allowlisted IPs,
   even if a buggy caller reached this far. Last write before nginx
   reload; last place to stop a bad ban.

4. admin_ban_ip: replace `ip.startswith("192.168.")` substring
   check with the canonical ALLOWLIST_IPS membership test. Pre-fix
   this only protected one LAN; 10.0.0.0/8, IPv6 loopback ::1, and
   custom allowlist entries (e.g. an external monitoring IP) were
   all banable by manual admin error. Now uses the same allowlist
   as the auto-ban paths.

Operationally the admin can no longer self-ban through any path.
The auto-escalate ban audit log entries get a corresponding
"AUTO_ESCALATE_BLOCKED ip=... — allowlisted" entry instead of the
ban firing silently. Same for nginx_ban: NGINX_BAN_BLOCKED entries
log the saved bullet for operator review.

Builds on 939dfdd (OB-4 path-regex bypass) + 266de61 (rate_limit
eviction + auth_login IP gate). Together these three commits close
the LLM Team UI's ban-system self-foot-shoot vulnerability surface.

Outstanding from the scrum (architectural, separate session):
- OB-3 root-running web app + privileged shell calls
- Sentinel prompt-injection WARN

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 03:24:01 -05:00
Description
LLM Team UI - Full-stack local AI orchestration platform
9.2 MiB
Languages
Python 97.4%
Shell 2.6%