Avoid 302 redirect when rewrite-target value is not an absolute URL for ingress-nginx provider

This commit is contained in:
Gina A. 2026-04-16 16:54:07 +07:00 committed by GitHub
parent 036114bf17
commit 7cacf027a1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 21 additions and 2 deletions

View file

@ -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
}

View file

@ -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 {