diff --git a/pkg/api/handlers/utils/handler.go b/pkg/api/handlers/utils/handler.go index 2f441c94fb..069010eada 100644 --- a/pkg/api/handlers/utils/handler.go +++ b/pkg/api/handlers/utils/handler.go @@ -120,7 +120,7 @@ func WriteJSON(w http.ResponseWriter, code int, value interface{}) { w.WriteHeader(code) coder := json.NewEncoder(w) - coder.SetEscapeHTML(true) + coder.SetEscapeHTML(false) if err := coder.Encode(value); err != nil { logrus.Errorf("Unable to write json: %q", err) } diff --git a/pkg/api/handlers/utils/handler_test.go b/pkg/api/handlers/utils/handler_test.go index 4df0f08042..1b2128656e 100644 --- a/pkg/api/handlers/utils/handler_test.go +++ b/pkg/api/handlers/utils/handler_test.go @@ -3,6 +3,9 @@ package utils import ( + "net/http/httptest" + "reflect" + "strings" "testing" ) @@ -53,3 +56,54 @@ func TestErrorEncoderFuncOmit(t *testing.T) { t.Errorf("the `errs` field shouldn't have been omitted") } } + +func TestWriteJSONNoHTMLEscape(t *testing.T) { + // Test that WriteJSON does not HTML-escape JSON content + // This test verifies the fix for issue #17769 + + recorder := httptest.NewRecorder() + + // Test data with characters that would be HTML-escaped + testData := map[string]string{ + "message": "Hello & \"friends\"", + "script": "", + "url": "https://example.com/path?param=value&other=", + } + + WriteJSON(recorder, 200, testData) + + // Check response headers + if contentType := recorder.Header().Get("Content-Type"); contentType != "application/json" { + t.Errorf("Expected Content-Type 'application/json', got '%s'", contentType) + } + + // Check that response contains unescaped characters + body := recorder.Body.String() + + // These characters should NOT be HTML-escaped in JSON responses + // (but quotes are still properly JSON-escaped) + expectedUnescaped := []string{ + "", + "&", + "\\\"friends\\\"", // JSON-escaped quotes, not HTML-escaped + "