diff --git a/services/hermes/router/main.go b/services/hermes/router/main.go index db115242..8ce9827f 100644 --- a/services/hermes/router/main.go +++ b/services/hermes/router/main.go @@ -395,6 +395,14 @@ func (router *tenantRouter) ServeHTTP(writer http.ResponseWriter, request *http. } { outbound.Header.Del(header) } + // HUX identity is asserted here, at the authenticated tenant boundary. + // Delete every browser-supplied HUX header before adding the one opaque + // subject that the same-pod WebUI BFF may trust. + for header := range outbound.Header { + if strings.HasPrefix(strings.ToLower(header), "x-hux-") { + outbound.Header.Del(header) + } + } // Each Keycloak subject is already mapped to exactly one isolated pod. // Give that pod a non-sensitive, router-asserted identity while retaining // only its own WebUI cookies; OAuth credentials never reach the backend. diff --git a/services/hermes/router/main_test.go b/services/hermes/router/main_test.go index d63b6348..e7d7f65d 100644 --- a/services/hermes/router/main_test.go +++ b/services/hermes/router/main_test.go @@ -106,6 +106,9 @@ func TestRouterProxiesWebUIAndAddsTelegramShortcut(t *testing.T) { if request.Header.Get(trustedTenantHeader) != "slot-0" { t.Fatalf("trusted tenant identity was not asserted: %q", request.Header.Get(trustedTenantHeader)) } + if request.Header.Get("X-Hux-Subject") != "" || request.Header.Get("X-Hux-Trust") != "" || request.Header.Get("X-Hux-Relay-Key") != "" { + t.Fatal("browser-supplied HUX trust headers reached the tenant backend") + } cookies := request.Cookies() if len(cookies) != 2 || cookies[0].Name != tenantSessionCookie || cookies[1].Name != tenantProfileCookie { t.Fatalf("unexpected backend cookies: %#v", cookies) @@ -121,6 +124,9 @@ func TestRouterProxiesWebUIAndAddsTelegramShortcut(t *testing.T) { request := httptest.NewRequest(http.MethodGet, "/", nil) request.Header.Set("X-Forwarded-User", "subject") request.Header.Set("X-Auth-Request-User", "subject") + request.Header.Set("X-Hux-Subject", "usr_0123456789abcdef") + request.Header.Set("X-Hux-Trust", "worker") + request.Header.Set("X-Hux-Relay-Key", "browser-forgery") request.Header.Set("Cookie", "_oauth2_proxy=secret; "+tenantSessionCookie+"=session; "+tenantProfileCookie+"=default") response := httptest.NewRecorder() router.ServeHTTP(response, request)