Skip to content

Commit 3bbe00d

Browse files
committed
Adds DOMPurify to sanitize clipboard markup
re: #21104 (review)
1 parent c3d9f48 commit 3bbe00d

File tree

1 file changed

+11
-5
lines changed

1 file changed

+11
-5
lines changed

src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/block/block.tiptap-api.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { UmbTiptapExtensionApiBase } from '../tiptap-extension-api-base.js';
22
import { umbRteBlock, umbRteBlockInline, umbRteBlockPaste } from './block.tiptap-extension.js';
33
import { distinctUntilChanged } from '@umbraco-cms/backoffice/external/rxjs';
4+
import { DOMPurify } from '@umbraco-cms/backoffice/external/dompurify';
45
import { UmbId } from '@umbraco-cms/backoffice/id';
56
import { UmbVariantId } from '@umbraco-cms/backoffice/variant';
67
import { UMB_BLOCK_RTE_DATA_CONTENT_KEY } from '@umbraco-cms/backoffice/rte';
@@ -50,9 +51,15 @@ export default class UmbTiptapBlockElementApi extends UmbTiptapExtensionApiBase
5051
return false;
5152
}
5253

53-
// Parse the HTML
54+
// Sanitize the HTML immediately to prevent XSS attacks while preserving RTE block elements
55+
const sanitizedHtml = DOMPurify.sanitize(html, {
56+
ADD_TAGS: ['umb-rte-block', 'umb-rte-block-inline'],
57+
ADD_ATTR: [UMB_BLOCK_RTE_DATA_CONTENT_KEY],
58+
});
59+
60+
// Parse the sanitized HTML
5461
const parser = new DOMParser();
55-
const doc = parser.parseFromString(html, 'text/html');
62+
const doc = parser.parseFromString(sanitizedHtml, 'text/html');
5663
const blockElements = doc.querySelectorAll('umb-rte-block, umb-rte-block-inline');
5764

5865
if (blockElements.length === 0) {
@@ -121,9 +128,8 @@ export default class UmbTiptapBlockElementApi extends UmbTiptapExtensionApiBase
121128
return false;
122129
}
123130

124-
// Get the modified HTML and insert it
125-
const modifiedHtml = doc.body.innerHTML;
126-
this._editor.commands.insertContent(modifiedHtml, { parseOptions: { preserveWhitespace: 'full' } });
131+
// Insert the modified HTML (already sanitized at function entry)
132+
this._editor.commands.insertContent(doc.body.innerHTML, { parseOptions: { preserveWhitespace: 'full' } });
127133

128134
// Return true to indicate we handled the paste
129135
return true;

0 commit comments

Comments
 (0)