From b28958cef929728fa9e6f30f4c813b2ee337f271 Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Wed, 4 Mar 2026 22:35:52 -0500 Subject: [PATCH] Revert "fix(chatd): sanitize \u0000 from JSON before JSONB insertion" (#22645) Reverts coder/coder#22637 --- coderd/chatd/chatprompt/chatprompt.go | 19 ---------------- coderd/chatd/chatprompt/chatprompt_test.go | 25 ---------------------- 2 files changed, 44 deletions(-) diff --git a/coderd/chatd/chatprompt/chatprompt.go b/coderd/chatd/chatprompt/chatprompt.go index 88c2c9f90f..ff6ad99368 100644 --- a/coderd/chatd/chatprompt/chatprompt.go +++ b/coderd/chatd/chatprompt/chatprompt.go @@ -1,7 +1,6 @@ package chatprompt import ( - "bytes" "encoding/json" "regexp" "strings" @@ -423,7 +422,6 @@ func MarshalContent(blocks []fantasy.Content) (pqtype.NullRawMessage, error) { if err != nil { return pqtype.NullRawMessage{}, xerrors.Errorf("encode content blocks: %w", err) } - data = sanitizeJSONForPG(data) return pqtype.NullRawMessage{RawMessage: data, Valid: true}, nil } @@ -441,7 +439,6 @@ func MarshalToolResult(toolCallID, toolName string, result json.RawMessage, isEr if err != nil { return pqtype.NullRawMessage{}, xerrors.Errorf("encode tool result: %w", err) } - data = sanitizeJSONForPG(data) return pqtype.NullRawMessage{RawMessage: data, Valid: true}, nil } @@ -838,22 +835,6 @@ func sanitizeToolCallID(id string) string { return toolCallIDSanitizer.ReplaceAllString(id, "_") } -// jsonNullEscape is the JSON escape sequence for Unicode null (U+0000). -var jsonNullEscape = []byte(`\u0000`) - -// sanitizeJSONForPG strips \u0000 escape sequences from JSON data. -// PostgreSQL's jsonb type rejects the Unicode null character (U+0000) -// with "unsupported Unicode escape sequence", even though \u0000 is -// valid JSON per RFC 8259. Tool results from agents may contain this -// sequence (e.g. binary data or C-style strings), so we strip it -// before insertion. -func sanitizeJSONForPG(data []byte) []byte { - if bytes.Contains(data, jsonNullEscape) { - data = bytes.ReplaceAll(data, jsonNullEscape, nil) - } - return data -} - func marshalContentBlock(block fantasy.Content) (json.RawMessage, error) { encoded, err := json.Marshal(block) if err != nil { diff --git a/coderd/chatd/chatprompt/chatprompt_test.go b/coderd/chatd/chatprompt/chatprompt_test.go index 684e9c2328..ba398446a1 100644 --- a/coderd/chatd/chatprompt/chatprompt_test.go +++ b/coderd/chatd/chatprompt/chatprompt_test.go @@ -1,7 +1,6 @@ package chatprompt_test import ( - "bytes" "encoding/json" "testing" @@ -90,27 +89,3 @@ func TestConvertMessages_NormalizesAssistantToolCallInput(t *testing.T) { }) } } - -func TestMarshalToolResult_SanitizesNullBytes(t *testing.T) { - t.Parallel() - - result := json.RawMessage(`{"output":"hello\u0000world"}`) - got, err := chatprompt.MarshalToolResult("call_1", "my_tool", result, false) - require.NoError(t, err) - require.True(t, got.Valid) - require.False(t, bytes.Contains(got.RawMessage, []byte(`\u0000`)), - "output should not contain \\u0000 escape sequences") -} - -func TestMarshalContent_SanitizesNullBytes(t *testing.T) { - t.Parallel() - - blocks := []fantasy.Content{ - fantasy.TextContent{Text: "before\u0000after"}, - } - got, err := chatprompt.MarshalContent(blocks) - require.NoError(t, err) - require.True(t, got.Valid) - require.False(t, bytes.Contains(got.RawMessage, []byte(`\u0000`)), - "output should not contain \\u0000 escape sequences") -}