From 2b9ffc426122b89bf38139cebfd7dfb8d5007634 Mon Sep 17 00:00:00 2001 From: Kevin Pollet Date: Tue, 14 Apr 2026 09:48:05 +0200 Subject: [PATCH] Use QuoteMeta for cookie name when building canary rules --- .../fixtures/ingresses/ingresses-with-canary-by-cookie.yml | 2 +- pkg/provider/kubernetes/ingress-nginx/kubernetes.go | 4 ++-- pkg/provider/kubernetes/ingress-nginx/kubernetes_test.go | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/provider/kubernetes/ingress-nginx/fixtures/ingresses/ingresses-with-canary-by-cookie.yml b/pkg/provider/kubernetes/ingress-nginx/fixtures/ingresses/ingresses-with-canary-by-cookie.yml index 3d8861a057..20a87bf56e 100644 --- a/pkg/provider/kubernetes/ingress-nginx/fixtures/ingresses/ingresses-with-canary-by-cookie.yml +++ b/pkg/provider/kubernetes/ingress-nginx/fixtures/ingresses/ingresses-with-canary-by-cookie.yml @@ -27,7 +27,7 @@ metadata: namespace: default annotations: nginx.ingress.kubernetes.io/canary: "true" - nginx.ingress.kubernetes.io/canary-by-cookie: "foo" + nginx.ingress.kubernetes.io/canary-by-cookie: "foo.bar" spec: ingressClassName: nginx diff --git a/pkg/provider/kubernetes/ingress-nginx/kubernetes.go b/pkg/provider/kubernetes/ingress-nginx/kubernetes.go index d9326df61a..c78d8e7325 100644 --- a/pkg/provider/kubernetes/ingress-nginx/kubernetes.go +++ b/pkg/provider/kubernetes/ingress-nginx/kubernetes.go @@ -147,7 +147,7 @@ func (c canaryBackend) AppendCanaryRule(rule string) string { } if c.Cookie != "" { - cookieRule := fmt.Sprintf(`HeaderRegexp("Cookie", %q)`, fmt.Sprintf("(^|;\\s*)%s=always(;|$)", c.Cookie)) + cookieRule := fmt.Sprintf(`HeaderRegexp("Cookie", %q)`, fmt.Sprintf("(^|;\\s*)%s=always(;|$)", regexp.QuoteMeta(c.Cookie))) if c.Header != "" && c.HeaderValue == "" && c.HeaderPattern == "" { cookieRule = fmt.Sprintf("(%s && !%s)", cookieRule, fmt.Sprintf(`Header(%q, "never")`, c.Header)) } @@ -165,7 +165,7 @@ func (c canaryBackend) AppendNonCanaryRule(rule string) string { rules = append(rules, fmt.Sprintf(`Header(%q, "never")`, c.Header)) } if c.Cookie != "" { - rules = append(rules, fmt.Sprintf(`HeaderRegexp("Cookie", %q)`, fmt.Sprintf("(^|;\\s*)%s=never(;|$)", c.Cookie))) + rules = append(rules, fmt.Sprintf(`HeaderRegexp("Cookie", %q)`, fmt.Sprintf("(^|;\\s*)%s=never(;|$)", regexp.QuoteMeta(c.Cookie)))) } return fmt.Sprintf("(%s) && (%s)", rule, strings.Join(rules, " || ")) diff --git a/pkg/provider/kubernetes/ingress-nginx/kubernetes_test.go b/pkg/provider/kubernetes/ingress-nginx/kubernetes_test.go index 8b8d91e1b7..9006dcfb60 100644 --- a/pkg/provider/kubernetes/ingress-nginx/kubernetes_test.go +++ b/pkg/provider/kubernetes/ingress-nginx/kubernetes_test.go @@ -11070,7 +11070,7 @@ func TestLoadIngresses(t *testing.T) { }, "default-ingress-with-canary-by-cookie-rule-0-path-0-canary": { EntryPoints: []string{"http"}, - Rule: `(Host("production.localhost") && PathPrefix("/")) && (HeaderRegexp("Cookie", "(^|;\\s*)foo=always(;|$)"))`, + Rule: `(Host("production.localhost") && PathPrefix("/")) && (HeaderRegexp("Cookie", "(^|;\\s*)foo\\.bar=always(;|$)"))`, RuleSyntax: "default", Service: "default-ingress-with-canary-by-cookie-whoami-80-canary", Observability: &dynamic.RouterObservabilityConfig{ @@ -11105,7 +11105,7 @@ func TestLoadIngresses(t *testing.T) { }, "default-ingress-with-canary-by-cookie-rule-0-path-0-canary-tls": { EntryPoints: []string{"https"}, - Rule: `(Host("production.localhost") && PathPrefix("/")) && (HeaderRegexp("Cookie", "(^|;\\s*)foo=always(;|$)"))`, + Rule: `(Host("production.localhost") && PathPrefix("/")) && (HeaderRegexp("Cookie", "(^|;\\s*)foo\\.bar=always(;|$)"))`, RuleSyntax: "default", Service: "default-ingress-with-canary-by-cookie-whoami-80-canary", Observability: &dynamic.RouterObservabilityConfig{