From c0b1ff31e5c51c539510b3d65e58dba0d95f678c Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 18 Apr 2026 09:56:41 +0300 Subject: [PATCH] fix(server): safe import strips out bookmarks from note --- .../src/services/html_sanitizer.spec.ts | 22 +++++++++++++++++++ apps/server/src/services/html_sanitizer.ts | 1 + 2 files changed, 23 insertions(+) diff --git a/apps/server/src/services/html_sanitizer.spec.ts b/apps/server/src/services/html_sanitizer.spec.ts index dfbba8fd71..6af366a329 100644 --- a/apps/server/src/services/html_sanitizer.spec.ts +++ b/apps/server/src/services/html_sanitizer.spec.ts @@ -50,4 +50,26 @@ describe("sanitize", () => { `; expect(html_sanitizer.sanitize(dirty)).toBe(clean); }); + + describe("bookmark anchors", () => { + it("preserves id attribute on empty tags (CKEditor bookmarks)", () => { + const dirty = ``; + expect(html_sanitizer.sanitize(dirty)).toBe(dirty); + }); + + it("preserves id attribute on tags with bookmark class", () => { + const dirty = ``; + expect(html_sanitizer.sanitize(dirty)).toBe(dirty); + }); + + it("strips id attribute from non-anchor tags to prevent DOM clobbering", () => { + const dirty = `
content
`; + expect(html_sanitizer.sanitize(dirty)).toBe(`
content
`); + }); + + it("strips id attribute from tags to prevent DOM clobbering", () => { + const dirty = ``; + expect(html_sanitizer.sanitize(dirty)).toBe(``); + }); + }); }); diff --git a/apps/server/src/services/html_sanitizer.ts b/apps/server/src/services/html_sanitizer.ts index f304dcf150..76262c2a32 100644 --- a/apps/server/src/services/html_sanitizer.ts +++ b/apps/server/src/services/html_sanitizer.ts @@ -42,6 +42,7 @@ function sanitize(dirtyHtml: string) { allowedTags: allowedTags as string[], allowedAttributes: { "*": ["class", "style", "title", "src", "href", "hash", "disabled", "align", "alt", "center", "data-*"], + a: ["id"], // CKEditor bookmark anchors use input: ["type", "checked"], img: ["width", "height"], code: [ "spellcheck" ]