From 72f99b88fbc986386dc3aa2a2ee6bd82de4c7180 Mon Sep 17 00:00:00 2001 From: Jiayuan Zhang Date: Sun, 12 Apr 2026 17:06:45 +0800 Subject: [PATCH] fix(sanitize): preserve code blocks and inline code from HTML entity escaping MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bluemonday operates on raw text, so characters like && and <> inside markdown code blocks/inline code were being HTML-escaped (e.g. && → &&), causing them to render incorrectly in the frontend. Now extracts fenced code blocks and inline code spans before sanitization, runs bluemonday on the remaining content, then restores the code verbatim. --- server/internal/sanitize/html.go | 48 +++++++++++++++++++++++---- server/internal/sanitize/html_test.go | 46 +++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 6 deletions(-) diff --git a/server/internal/sanitize/html.go b/server/internal/sanitize/html.go index 89ca4e094..5d1971f37 100644 --- a/server/internal/sanitize/html.go +++ b/server/internal/sanitize/html.go @@ -1,7 +1,9 @@ package sanitize import ( + "fmt" "regexp" + "strings" "github.com/microcosm-cc/bluemonday" ) @@ -11,11 +13,6 @@ var httpURL = regexp.MustCompile(`^https?://`) // policy is a shared bluemonday policy that allows safe Markdown HTML while // stripping dangerous elements (script, iframe, object, embed, style, on*). -// -// Note: bluemonday operates on raw text, so HTML inside Markdown code blocks -// (e.g. ```\n```", + want: "```\n\n```", + }, + { + name: "script outside code block still stripped", + input: "hello world", + want: "hello world", + }, + { + name: "mixed code and non-code", + input: "text `a && b` more end", + want: "text `a && b` more end", + }, + { + name: "tilde fenced code block preserves content", + input: "~~~\na && b\n~~~", + want: "~~~\na && b\n~~~", + }, } for _, tt := range tests {