diff --git a/backend/internal/config/config.go b/backend/internal/config/config.go index aeaadb2d..2976cf13 100644 --- a/backend/internal/config/config.go +++ b/backend/internal/config/config.go @@ -957,6 +957,16 @@ func (c *Config) Validate() error { if err := ValidateAbsoluteHTTPURL(c.Server.FrontendURL); err != nil { return fmt.Errorf("server.frontend_url invalid: %w", err) } + u, err := url.Parse(strings.TrimSpace(c.Server.FrontendURL)) + if err != nil { + return fmt.Errorf("server.frontend_url invalid: %w", err) + } + if u.RawQuery != "" || u.ForceQuery { + return fmt.Errorf("server.frontend_url invalid: must not include query") + } + if u.User != nil { + return fmt.Errorf("server.frontend_url invalid: must not include userinfo") + } warnIfInsecureURL("server.frontend_url", c.Server.FrontendURL) } if c.JWT.ExpireHour <= 0 { diff --git a/backend/internal/config/config_test.go b/backend/internal/config/config_test.go index 5fd2672a..4bde837f 100644 --- a/backend/internal/config/config_test.go +++ b/backend/internal/config/config_test.go @@ -437,6 +437,21 @@ func TestValidateServerFrontendURL(t *testing.T) { t.Fatalf("Validate() frontend_url valid error: %v", err) } + cfg.Server.FrontendURL = "https://example.com/path" + if err := cfg.Validate(); err != nil { + t.Fatalf("Validate() frontend_url with path valid error: %v", err) + } + + cfg.Server.FrontendURL = "https://example.com?utm=1" + if err := cfg.Validate(); err == nil { + t.Fatalf("Validate() should reject server.frontend_url with query") + } + + cfg.Server.FrontendURL = "https://user:pass@example.com" + if err := cfg.Validate(); err == nil { + t.Fatalf("Validate() should reject server.frontend_url with userinfo") + } + cfg.Server.FrontendURL = "/relative" if err := cfg.Validate(); err == nil { t.Fatalf("Validate() should reject relative server.frontend_url")