From f5c3094050566d8d4fcf9f3ecf7d26f9c3241c65 Mon Sep 17 00:00:00 2001 From: Gilbert Gilb's Date: Tue, 23 Sep 2025 05:12:06 +0200 Subject: [PATCH] cmd: prevent commas in header values from being split (#7268) `pflag.GetStringSlice` treats commas as delimiters, which causes issues when passing headers whose values contain commas (`X-Robots-Tag: noindex, nofollow`). These are incorrectly split into multiple headers and errors out: - `X-Robots-Tag: noindex` - ` nofollow` Switch to `pflag.GetStringArray`, which does not split on commas[1]. Note that this changes behavior for cases where multiple headers were provided in a single argument with commas (`--header-down "X-Foo: Bar,X-Bar: Foo"`). Such cases will now be treated as a single header value. If this breaking change is unacceptable, we will need a smarter fallback mechanism. [1] https://github.com/spf13/pflag/pull/90 --- modules/caddyhttp/reverseproxy/command.go | 8 ++++---- modules/caddyhttp/staticresp.go | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/caddyhttp/reverseproxy/command.go b/modules/caddyhttp/reverseproxy/command.go index 54955bcf7..3f6ffa8cb 100644 --- a/modules/caddyhttp/reverseproxy/command.go +++ b/modules/caddyhttp/reverseproxy/command.go @@ -75,8 +75,8 @@ For proxying: cmd.Flags().BoolP("insecure", "", false, "Disable TLS verification (WARNING: DISABLES SECURITY BY NOT VERIFYING TLS CERTIFICATES!)") cmd.Flags().BoolP("disable-redirects", "r", false, "Disable HTTP->HTTPS redirects") cmd.Flags().BoolP("internal-certs", "i", false, "Use internal CA for issuing certs") - cmd.Flags().StringSliceP("header-up", "H", []string{}, "Set a request header to send to the upstream (format: \"Field: value\")") - cmd.Flags().StringSliceP("header-down", "d", []string{}, "Set a response header to send back to the client (format: \"Field: value\")") + cmd.Flags().StringArrayP("header-up", "H", []string{}, "Set a request header to send to the upstream (format: \"Field: value\")") + cmd.Flags().StringArrayP("header-down", "d", []string{}, "Set a response header to send back to the client (format: \"Field: value\")") cmd.Flags().BoolP("access-log", "", false, "Enable the access log") cmd.Flags().BoolP("debug", "v", false, "Enable verbose debug logs") cmd.RunE = caddycmd.WrapCommandFuncForCobra(cmdReverseProxy) @@ -182,7 +182,7 @@ func cmdReverseProxy(fs caddycmd.Flags) (int, error) { } // set up header_up - headerUp, err := fs.GetStringSlice("header-up") + headerUp, err := fs.GetStringArray("header-up") if err != nil { return caddy.ExitCodeFailedStartup, fmt.Errorf("invalid header flag: %v", err) } @@ -204,7 +204,7 @@ func cmdReverseProxy(fs caddycmd.Flags) (int, error) { } // set up header_down - headerDown, err := fs.GetStringSlice("header-down") + headerDown, err := fs.GetStringArray("header-down") if err != nil { return caddy.ExitCodeFailedStartup, fmt.Errorf("invalid header flag: %v", err) } diff --git a/modules/caddyhttp/staticresp.go b/modules/caddyhttp/staticresp.go index 12108ac03..d783d1b04 100644 --- a/modules/caddyhttp/staticresp.go +++ b/modules/caddyhttp/staticresp.go @@ -79,7 +79,7 @@ Response headers may be added using the --header flag for each header field. cmd.Flags().StringP("body", "b", "", "The body of the HTTP response") cmd.Flags().BoolP("access-log", "", false, "Enable the access log") cmd.Flags().BoolP("debug", "v", false, "Enable more verbose debug-level logging") - cmd.Flags().StringSliceP("header", "H", []string{}, "Set a header on the response (format: \"Field: value\")") + cmd.Flags().StringArrayP("header", "H", []string{}, "Set a header on the response (format: \"Field: value\")") cmd.RunE = caddycmd.WrapCommandFuncForCobra(cmdRespond) }, }) @@ -359,7 +359,7 @@ func cmdRespond(fl caddycmd.Flags) (int, error) { } // build headers map - headers, err := fl.GetStringSlice("header") + headers, err := fl.GetStringArray("header") if err != nil { return caddy.ExitCodeFailedStartup, fmt.Errorf("invalid header flag: %v", err) }