Skip to content

Commit 33590a1

Browse files
authored
IBX-10288: Fix XSS in custom tags
1 parent 00554a9 commit 33590a1

File tree

2 files changed

+19
-9
lines changed

2 files changed

+19
-9
lines changed

src/bundle/Resources/public/js/CKEditor/custom-tags/block-custom-tag/custom-tag-editing.js

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ import { toWidget, toWidgetEditable } from '@ckeditor/ckeditor5-widget/src/utils
44

55
import IbexaCustomTagCommand from './custom-tag-command';
66

7+
const { escapeHTML, escapeHTMLAttribute } = window.ibexa.helpers.text;
8+
const { dangerouslySetInnerHTML } = window.ibexa.helpers.dom;
9+
710
class IbexaCustomTagEditing extends Plugin {
811
static get requires() {
912
return [Widget];
@@ -68,18 +71,18 @@ class IbexaCustomTagEditing extends Plugin {
6871
const config = downcastWriter.createUIElement('span', { 'data-ezelement': 'ezconfig' }, function (domDocument) {
6972
const domElement = this.toDomElement(domDocument);
7073

71-
domElement.innerHTML = Object.entries(values).reduce((total, [attribute, value]) => {
72-
// Escaping
73-
// <script>alert("Hello! I am a script!");</script> --> &lt;script&gt;alert("Hello! I am a script!");&lt;/script&gt;
74-
const stringTempNode = domDocument.createElement('div');
75-
stringTempNode.appendChild(domDocument.createTextNode(value !== null ? value : ''));
76-
const attributeValue = stringTempNode.innerHTML;
74+
const attributesHTMLCode = Object.entries(values).reduce((total, [attributeName, value]) => {
75+
const attributeValue = value ?? '';
76+
const attributeValueEscaped = escapeHTML(attributeValue);
77+
const attributeNameAttributeEscaped = escapeHTMLAttribute(attributeName);
7778

78-
const ezvalue = `<span data-ezelement="ezvalue" data-ezvalue-key="${attribute}">${attributeValue}</span>`;
79+
const ezvalue = `<span data-ezelement="ezvalue" data-ezvalue-key="${attributeNameAttributeEscaped}">${attributeValueEscaped}</span>`;
7980

8081
return `${total}${ezvalue}`;
8182
}, '');
8283

84+
dangerouslySetInnerHTML(domElement, attributesHTMLCode);
85+
8386
return domElement;
8487
});
8588

src/bundle/Resources/public/js/CKEditor/custom-tags/inline-custom-tag/inline-custom-tag-editing.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ import Element from '@ckeditor/ckeditor5-engine/src/view/element';
55

66
import IbexaInlineCustomTagCommand from './inline-custom-tag-command';
77

8+
const { escapeHTML, escapeHTMLAttribute } = window.ibexa.helpers.text;
9+
const { dangerouslySetInnerHTML } = window.ibexa.helpers.dom;
10+
811
class IbexaInlineCustomTagEditing extends Plugin {
912
static get requires() {
1013
return [Widget];
@@ -54,13 +57,17 @@ class IbexaInlineCustomTagEditing extends Plugin {
5457
const config = downcastWriter.createUIElement('span', { 'data-ezelement': 'ezconfig' }, function (domDocument) {
5558
const domElement = this.toDomElement(domDocument);
5659

57-
domElement.innerHTML = Object.entries(values).reduce((total, [attribute, value]) => {
60+
const attributesHTMLCode = Object.entries(values).reduce((total, [attributeName, value]) => {
5861
const attributeValue = value ?? '';
59-
const ezvalue = `<span data-ezelement="ezvalue" data-ezvalue-key="${attribute}">${attributeValue}</span>`;
62+
const attributeValueEscaped = escapeHTML(attributeValue);
63+
const attributeNameAttributeEscaped = escapeHTMLAttribute(attributeName);
64+
const ezvalue = `<span data-ezelement="ezvalue" data-ezvalue-key="${attributeNameAttributeEscaped}">${attributeValueEscaped}</span>`;
6065

6166
return `${total}${ezvalue}`;
6267
}, '');
6368

69+
dangerouslySetInnerHTML(domElement, attributesHTMLCode);
70+
6471
return domElement;
6572
});
6673

0 commit comments

Comments
 (0)