Root cause
Authentication & access control introduced
The route starts an embedded terminal through the existing API dispatcher.
How AI contributed: Direct introductionPublished Jul 10, 2026 in
nesquena/hermes-webuiAll 6 findings in this repository
Provisional finding. Full causal and release verification remains incomplete.
Root cause
The route starts an embedded terminal through the existing API dispatcher.
Fix
The terminal gate delegates unauthenticated deployments to the existing local-origin policy.
Case facts
@@ -1518,3 +1533,15 @@ from api.streaming import _handle_chat_steer return _handle_chat_steer(handler, body) + if parsed.path == "/api/terminal/start":+ return _handle_terminal_start(handler, body)++ if parsed.path == "/api/terminal/input":+ return _handle_terminal_input(handler, body)++ if parsed.path == "/api/terminal/resize":+ return _handle_terminal_resize(handler, body)++ if parsed.path == "/api/terminal/close":+ return _handle_terminal_close(handler, body)+@@ -5082,3 +5098,12 @@+ admits every caller unconditionally, so restrict the terminal to local/private+ origins — the same trust model the onboarding/bootstrap endpoints use, ignoring+ spoofable forwarded headers unless an operator has opted into trusting them.+ A deliberately-exposed passwordless server (access secured at another layer)+ opts out with ``HERMES_WEBUI_ONBOARDING_OPEN=1``.+ """+ return _onboarding_gate_allows(handler)++ def _csp_report_rate_limited(handler, *, now: float | None = None) -> bool: now = time.time() if now is None else now key = _client_ip_for_rate_limit(handler)AI-assisted change 44b005591f89887739925f493719b465d722116a1cca84116f79e07566232480 · Fix 0c9173da439c326115efc098e0ae1840273e6490a9a0675cb86095c68741160a