From 7cacf027a15df76b30cd3af5517fce49b3c1b565 Mon Sep 17 00:00:00 2001 From: "Gina A." <70909035+gndz07@users.noreply.github.com> Date: Thu, 16 Apr 2026 16:54:07 +0700 Subject: [PATCH] Avoid 302 redirect when rewrite-target value is not an absolute URL for ingress-nginx provider --- .../ingressnginx/rewritetarget/rewrite_target.go | 12 ++++++++++-- .../rewritetarget/rewrite_target_test.go | 11 +++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/pkg/middlewares/ingressnginx/rewritetarget/rewrite_target.go b/pkg/middlewares/ingressnginx/rewritetarget/rewrite_target.go index 8e8c4944b8..cf0df7f4b2 100644 --- a/pkg/middlewares/ingressnginx/rewritetarget/rewrite_target.go +++ b/pkg/middlewares/ingressnginx/rewritetarget/rewrite_target.go @@ -28,6 +28,9 @@ type rewriteTarget struct { replacement string xForwardedPrefix string name string + // absoluteURLRedirect is true when the replacement template is an absolute URL, + // indicating the operator explicitly configured a redirect to an external destination. + absoluteURLRedirect bool } // New creates a new rewrite target middleware. @@ -45,6 +48,10 @@ func New(ctx context.Context, next http.Handler, config dynamic.RewriteTarget, n name: name, } + if parsed, err := url.Parse(mw.replacement); err == nil && parsed.Scheme != "" { + mw.absoluteURLRedirect = true + } + if config.Regex != "" { exp, err := regexp.Compile(strings.TrimSpace(config.Regex)) if err != nil { @@ -77,8 +84,9 @@ func (rt *rewriteTarget) ServeHTTP(rw http.ResponseWriter, req *http.Request) { newTarget = replacementRegex.ReplaceAllString(rt.replacement, "") } - // If the replacement resolves to an absolute URL, issue a 302 redirect. - if parsed, err := url.Parse(newTarget); err == nil && parsed.Scheme != "" { + // Only issue a 302 redirect if the replacement template itself is an absolute URL. + // Prevent user-controlled capture group content from injecting an absolute URL redirect. + if rt.absoluteURLRedirect { http.Redirect(rw, req, newTarget, http.StatusFound) return } diff --git a/pkg/middlewares/ingressnginx/rewritetarget/rewrite_target_test.go b/pkg/middlewares/ingressnginx/rewritetarget/rewrite_target_test.go index eec5f38f26..decdc39416 100644 --- a/pkg/middlewares/ingressnginx/rewritetarget/rewrite_target_test.go +++ b/pkg/middlewares/ingressnginx/rewritetarget/rewrite_target_test.go @@ -171,6 +171,17 @@ func TestRewriteTarget(t *testing.T) { expectedStatusCode: http.StatusFound, expectedRedirectURL: "https://bar.example.org/", }, + { + desc: "path with an absolute redirect URL in the capture group should not issue a 302 redirect", + path: "/prefix/http://evil.com/malicious", + config: dynamic.RewriteTarget{ + Regex: `^/prefix/(.*)`, + Replacement: "$1", + }, + expectedPath: "http://evil.com/malicious", + expectedRawPath: "http://evil.com/malicious", + expectedStatusCode: http.StatusOK, + }, } for _, test := range testCases {