fix(dashboard): add Host allowlist for trusted reverse proxies - #48954
fix(dashboard): add Host allowlist for trusted reverse proxies#48954moeedahmed wants to merge 2 commits into
Conversation
Add HERMES_DASHBOARD_ALLOWED_HOSTS so a dashboard bound to 127.0.0.1 can accept requests forwarded by a trusted local reverse proxy (e.g. Tailscale Serve) whose Host header is the tailnet DNS name, without binding to a public interface. web_server.py: - Add _normalize_host_header() to extract the bare lowercase host portion from a Host header / netloc (plain, host:port, bracketed IPv6, and bracketed IPv6 with port). - Add _dashboard_allowed_host_aliases() reading the comma-separated env var into a frozenset of exact aliases (no wildcards). - Refactor _is_accepted_host() to reuse the normalizer and check the proxy aliases before the loopback/exact-match rules; document the lookup chain. AuthWidget.tsx: - Skip the /api/auth/me probe entirely in loopback / --insecure mode. The shared fetchJSON 401 handler can otherwise turn this expected 401 into a reload/flicker loop behind a reverse proxy. The widget already renders nothing in this mode, so gate the request on window.__HERMES_AUTH_REQUIRED__. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
tonydwb
left a comment
There was a problem hiding this comment.
Code Review Summary
Verdict: Approved
- Well-scoped fix adding Host allowlist for trusted reverse proxies (e.g. Tailscale Serve)
- Clean refactor: extracts _normalize_host_header into its own function, adds _dashboard_allowed_host_aliases reading from HERMES_DASHBOARD_ALLOWED_HOSTS env var
- Correct lookup chain: normalized host, then 0.0.0.0 opt-in, then allowlist, then loopback, then exact match
- IPv6 bracket handling properly preserved in the extracted normalization function
- AuthWidget.tsx fix: skips /api/auth/me probe when auth is not required, preventing reload/flicker loops behind trusted proxies - good defensive UX fix
- No wildcards in allowlist (exact match only) is the right security posture
- Minor formatting fix in AuthWidget.tsx span element is harmless
Reviewed by Hermes Agent
# Conflicts: # hermes_cli/web_server.py
|
Thanks for the focused reverse-proxy analysis and the Host-header regression coverage. This automated hermes-sweeper review is closing the PR because its remaining configuration mechanism conflicts with a standing project policy.
A focused re-scope to a documented Closed as not-planned per standing maintainer policy ( |
Adds HERMES_DASHBOARD_ALLOWED_HOSTS env var to allow specific Host headers when the dashboard is bound to 127.0.0.1 behind a trusted reverse proxy like Tailscale Serve.
Also fixes AuthWidget to skip /api/auth/me probe in loopback mode, preventing a reload/flicker loop behind reverse proxies.