From 20290ee1430096fe3e2a151277f6abc29bfd3982 Mon Sep 17 00:00:00 2001 From: Stavros Date: Sun, 4 Oct 2026 20:21:54 +0300 Subject: [PATCH 1/2] fix: use direct path value in envoy instead of query params --- internal/controller/proxy_controller.go | 4 ++-- internal/controller/proxy_controller_test.go | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/internal/controller/proxy_controller.go b/internal/controller/proxy_controller.go index 7349a2ca..7cdcb74b 100644 --- a/internal/controller/proxy_controller.go +++ b/internal/controller/proxy_controller.go @@ -465,8 +465,8 @@ func (controller *ProxyController) getExtAuthzContext(c *gin.Context) (ProxyCont return ProxyContext{}, errors.New("host not found") } - // We get the path from the query string - path := c.Query("path") + // The path is attached to the end of the /api/auth/envoy?path= string so we just strip it out + path := strings.TrimPrefix(c.Request.RequestURI, "/api/auth/envoy?path=") if strings.TrimSpace(path) == "" { return ProxyContext{}, errors.New("path not found") diff --git a/internal/controller/proxy_controller_test.go b/internal/controller/proxy_controller_test.go index fd06ae39..0bf0596d 100644 --- a/internal/controller/proxy_controller_test.go +++ b/internal/controller/proxy_controller_test.go @@ -903,6 +903,16 @@ func TestProxyController(t *testing.T) { assert.Equal(t, http.StatusBadRequest, recorder.Code) }, }, + { + description: "Ext authz path should not be treated as a query parameter", + run: func(t *testing.T, router *gin.Engine, recorder *httptest.ResponseRecorder) { + req := httptest.NewRequest("HEAD", "/api/auth/envoy?path=/admin?;&path=/allowed", nil) + req.Host = "path-allow.example.com" + req.Header.Set("x-forwarded-proto", "https") + router.ServeHTTP(recorder, req) + assert.Equal(t, http.StatusUnauthorized, recorder.Code) + }, + }, } store := memory.New() From aa2053fbb73868d052a0df3dd3cda93b190d3377 Mon Sep 17 00:00:00 2001 From: Stavros Date: Sun, 4 Oct 2026 23:20:12 +0300 Subject: [PATCH 2/2] tests: fix tests --- internal/controller/proxy_controller_test.go | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/internal/controller/proxy_controller_test.go b/internal/controller/proxy_controller_test.go index 0bf0596d..ef573663 100644 --- a/internal/controller/proxy_controller_test.go +++ b/internal/controller/proxy_controller_test.go @@ -169,7 +169,7 @@ func TestProxyController(t *testing.T) { router.ServeHTTP(recorder, req) assert.Equal(t, http.StatusFound, recorder.Code) location := recorder.Header().Get("Location") - assert.Contains(t, location, url.QueryEscape("https://test.example.com/hello?foo=bar")) + assert.Contains(t, location, url.QueryEscape("https://test.example.com%2Fhello%3Ffoo%3Dbar")) assert.Contains(t, location, "login_for=app") assert.Contains(t, location, "https://tinyauth.example.com/login") }, @@ -464,17 +464,6 @@ func TestProxyController(t *testing.T) { assert.Equal(t, http.StatusBadRequest, recorder.Code) }, }, - { - description: "Ensure path block ACL cannot be bypassed with query params on envoy ext authz", - middlewares: []gin.HandlerFunc{}, - run: func(t *testing.T, router *gin.Engine, recorder *httptest.ResponseRecorder) { - req := httptest.NewRequest("HEAD", "/api/auth/envoy?path=/admin%3Ffoo=bar", nil) - req.Host = "path-block.example.com" - req.Header.Set("x-forwarded-proto", "https") - router.ServeHTTP(recorder, req) - assert.Equal(t, http.StatusUnauthorized, recorder.Code) - }, - }, { description: "Ensure path block ACL cannot be bypassed with dot segments on nginx auth request", middlewares: []gin.HandlerFunc{},