From 7fb9ec93e47cec39a548a76e03d7ad660ca0f123 Mon Sep 17 00:00:00 2001 From: Laurent Cozic Date: Sat, 22 Aug 2026 10:36:36 +0100 Subject: [PATCH] Desktop: Strip style elements from whiteboard card content (#16275) --- .gitignore | 2 + .ignore.eslint | 2 + .../WhiteboardEditor/nodes/FileNode.tsx | 3 +- .../WhiteboardEditor/nodes/TextNode.tsx | 3 +- .../nodes/stripUnsafeStyles.test.ts | 48 +++++++++++++++++++ .../nodes/stripUnsafeStyles.ts | 15 ++++++ 6 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 packages/app-desktop/gui/NoteEditor/NoteBody/WhiteboardEditor/nodes/stripUnsafeStyles.test.ts create mode 100644 packages/app-desktop/gui/NoteEditor/NoteBody/WhiteboardEditor/nodes/stripUnsafeStyles.ts diff --git a/.gitignore b/.gitignore index fc95eca96c..360bcce61c 100644 --- a/.gitignore +++ b/.gitignore @@ -319,6 +319,8 @@ packages/app-desktop/gui/NoteEditor/NoteBody/WhiteboardEditor/nodes/GroupNode.js packages/app-desktop/gui/NoteEditor/NoteBody/WhiteboardEditor/nodes/LinkNode.js packages/app-desktop/gui/NoteEditor/NoteBody/WhiteboardEditor/nodes/TextNode.js packages/app-desktop/gui/NoteEditor/NoteBody/WhiteboardEditor/nodes/handlePositions.js +packages/app-desktop/gui/NoteEditor/NoteBody/WhiteboardEditor/nodes/stripUnsafeStyles.test.js +packages/app-desktop/gui/NoteEditor/NoteBody/WhiteboardEditor/nodes/stripUnsafeStyles.js packages/app-desktop/gui/NoteEditor/NoteBody/WhiteboardEditor/nodes/useCardWheel.js packages/app-desktop/gui/NoteEditor/NoteBody/WhiteboardEditor/useCheckboxToggle.test.js packages/app-desktop/gui/NoteEditor/NoteBody/WhiteboardEditor/useCheckboxToggle.js diff --git a/.ignore.eslint b/.ignore.eslint index 7269c19b8a..2d87675a39 100644 --- a/.ignore.eslint +++ b/.ignore.eslint @@ -344,6 +344,8 @@ packages/app-desktop/gui/NoteEditor/NoteBody/WhiteboardEditor/nodes/GroupNode.js packages/app-desktop/gui/NoteEditor/NoteBody/WhiteboardEditor/nodes/LinkNode.js packages/app-desktop/gui/NoteEditor/NoteBody/WhiteboardEditor/nodes/TextNode.js packages/app-desktop/gui/NoteEditor/NoteBody/WhiteboardEditor/nodes/handlePositions.js +packages/app-desktop/gui/NoteEditor/NoteBody/WhiteboardEditor/nodes/stripUnsafeStyles.test.js +packages/app-desktop/gui/NoteEditor/NoteBody/WhiteboardEditor/nodes/stripUnsafeStyles.js packages/app-desktop/gui/NoteEditor/NoteBody/WhiteboardEditor/nodes/useCardWheel.js packages/app-desktop/gui/NoteEditor/NoteBody/WhiteboardEditor/useCheckboxToggle.test.js packages/app-desktop/gui/NoteEditor/NoteBody/WhiteboardEditor/useCheckboxToggle.js diff --git a/packages/app-desktop/gui/NoteEditor/NoteBody/WhiteboardEditor/nodes/FileNode.tsx b/packages/app-desktop/gui/NoteEditor/NoteBody/WhiteboardEditor/nodes/FileNode.tsx index 64c08e3920..577a2fca81 100644 --- a/packages/app-desktop/gui/NoteEditor/NoteBody/WhiteboardEditor/nodes/FileNode.tsx +++ b/packages/app-desktop/gui/NoteEditor/NoteBody/WhiteboardEditor/nodes/FileNode.tsx @@ -20,6 +20,7 @@ import { WhiteboardNodeData } from '../canvasFlow'; import useCheckboxToggle from '../useCheckboxToggle'; import handlePositions from './handlePositions'; import useCardWheel from './useCardWheel'; +import stripUnsafeStyles from './stripUnsafeStyles'; const logger = Logger.create('WhiteboardFileNode'); @@ -124,7 +125,7 @@ const FileNode = ({ data, selected }: NodeProps<{ id: string; type: 'wbFile'; da const result = await ctx.markupToHtml(MarkupLanguage.Markdown, resolved.body, { resourceInfos: linkedResources, }); - if (!cancelled) setNoteHtml(result?.html ?? ''); + if (!cancelled) setNoteHtml(stripUnsafeStyles(result?.html ?? '')); } catch { if (!cancelled) setNoteHtml(''); } diff --git a/packages/app-desktop/gui/NoteEditor/NoteBody/WhiteboardEditor/nodes/TextNode.tsx b/packages/app-desktop/gui/NoteEditor/NoteBody/WhiteboardEditor/nodes/TextNode.tsx index e8d20464e7..05c26f406f 100644 --- a/packages/app-desktop/gui/NoteEditor/NoteBody/WhiteboardEditor/nodes/TextNode.tsx +++ b/packages/app-desktop/gui/NoteEditor/NoteBody/WhiteboardEditor/nodes/TextNode.tsx @@ -11,6 +11,7 @@ import { WhiteboardNodeData } from '../canvasFlow'; import useCheckboxToggle from '../useCheckboxToggle'; import handlePositions from './handlePositions'; import useCardWheel from './useCardWheel'; +import stripUnsafeStyles from './stripUnsafeStyles'; const useRenderedMarkdown = (md: string, ctx: WhiteboardContextValue) => { const [html, setHtml] = useState(''); @@ -26,7 +27,7 @@ const useRenderedMarkdown = (md: string, ctx: WhiteboardContextValue) => { const result = await ctx.markupToHtml(MarkupLanguage.Markdown, md, { resourceInfos: ctx.resourceInfos, }); - if (!cancelled) setHtml(result?.html ?? ''); + if (!cancelled) setHtml(stripUnsafeStyles(result?.html ?? '')); } catch { if (!cancelled) setHtml(''); } diff --git a/packages/app-desktop/gui/NoteEditor/NoteBody/WhiteboardEditor/nodes/stripUnsafeStyles.test.ts b/packages/app-desktop/gui/NoteEditor/NoteBody/WhiteboardEditor/nodes/stripUnsafeStyles.test.ts new file mode 100644 index 0000000000..bf490fca22 --- /dev/null +++ b/packages/app-desktop/gui/NoteEditor/NoteBody/WhiteboardEditor/nodes/stripUnsafeStyles.test.ts @@ -0,0 +1,48 @@ +import stripUnsafeStyles from './stripUnsafeStyles'; + +describe('stripUnsafeStyles', () => { + + test.each([ + [ + 'removes a style element', + '

Hello

', + '

Hello

', + ], + [ + 'removes a style element containing a remote @import', + '

Hi

', + '

Hi

', + ], + [ + 'removes multiple style elements', + '

x

', + '

x

', + ], + [ + 'removes an uppercase STYLE element', + '

x

', + '

x

', + ], + [ + 'removes a mixed-case Style element', + '

y

', + '

y

', + ], + [ + 'keeps rich card content (images, formatting, links)', + '

Bold link

', + '

Bold link

', + ], + [ + 'keeps inline style attributes, which cannot reach the app chrome', + '

text

', + '

text

', + ], + ])('should %s', (_label, input, expected) => { + expect(stripUnsafeStyles(input)).toBe(expected); + }); + + test('should return empty input unchanged', () => { + expect(stripUnsafeStyles('')).toBe(''); + }); +}); diff --git a/packages/app-desktop/gui/NoteEditor/NoteBody/WhiteboardEditor/nodes/stripUnsafeStyles.ts b/packages/app-desktop/gui/NoteEditor/NoteBody/WhiteboardEditor/nodes/stripUnsafeStyles.ts new file mode 100644 index 0000000000..479c655d17 --- /dev/null +++ b/packages/app-desktop/gui/NoteEditor/NoteBody/WhiteboardEditor/nodes/stripUnsafeStyles.ts @@ -0,0 +1,15 @@ +// Whiteboard cards render into the main document, not the isolated note-viewer +// iframe, so a note's