Skip to content

Commit

Permalink
[SS-2023-002] Apply tinymce patches for XSS vulnerabilities
Browse files Browse the repository at this point in the history
  • Loading branch information
GuySartorelli authored and emteknetnz committed Jul 30, 2023
1 parent 50f72e5 commit cafc1c4
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 32 deletions.
8 changes: 8 additions & 0 deletions thirdparty/tinymce/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# THIS PACKAGE CONTAINS MODIFICATIONS

This is not just a direct copy of tinymce 4.9.11 - it contains various security patches.

The source for this copy of tinymce is at https://github.com/silverstripe/tinymce/

To build out the dist files, simply follow the instructions in the readme of that repository, though note that you can run `npx grunt` instead of installing grunt if you want.
The relevant files will be in the `tmp/TinyMCE.4.9.11.nupkg` file that grunt builds out.
99 changes: 68 additions & 31 deletions thirdparty/tinymce/tinymce.js
Original file line number Diff line number Diff line change
Expand Up @@ -17630,11 +17630,19 @@
}
return sanitizedText;
};
var isInvalidUri = function (settings, uri) {
var safeSvgDataUrlElements = [
'img',
'video'
];
var blockSvgDataUris = function (allowSvgDataUrls, tagName) {
var allowed = allowSvgDataUrls === null || allowSvgDataUrls === undefined ? contains(safeSvgDataUrlElements, tagName) : allowSvgDataUrls;
return !allowed;
};
var isInvalidUri = function (settings, uri, tagName) {
if (settings.allow_html_data_urls) {
return false;
} else if (/^data:image\//i.test(uri)) {
return settings.allow_svg_data_urls === false && /^data:image\/svg\+xml/i.test(uri);
return blockSvgDataUris(settings.allow_svg_data_urls, tagName) && /^data:image\/svg\+xml/i.test(uri);
} else {
return /^data:/i.test(uri);
}
Expand Down Expand Up @@ -17717,7 +17725,7 @@
stack.length = pos;
}
};
var parseAttribute = function (match, name, value, val2, val3) {
var parseAttribute = function (tagName, name, value, val2, val3) {
var attrRule, i;
var trimRegExp = /[\s\u0000-\u001F]+/g;
name = name.toLowerCase();
Expand Down Expand Up @@ -17753,7 +17761,7 @@
if (scriptUriRegExp.test(uri)) {
return;
}
if (isInvalidUri(settings, uri)) {
if (isInvalidUri(settings, uri, tagName)) {
return;
}
}
Expand Down Expand Up @@ -17822,7 +17830,10 @@
}
attrList = [];
attrList.map = {};
attribsValue.replace(attrRegExp, parseAttribute);
attribsValue.replace(attrRegExp, function (match, name, val, val2, val3) {
parseAttribute(value, name, val, val2, val3);
return '';
});
} else {
attrList = [];
attrList.map = {};
Expand Down Expand Up @@ -20416,6 +20427,14 @@
}
return collection;
};
Node.prototype.children = function () {
var self = this;
var collection = [];
for (var node = self.firstChild; node; node = node.next) {
collection.push(node);
}
return collection;
};
Node.prototype.empty = function () {
var self = this;
var nodes, i, node;
Expand Down Expand Up @@ -20681,6 +20700,23 @@
whitespaceElements = schema.getWhiteSpaceElements();
textBlockElements = schema.getTextBlockElements();
specialElements = schema.getSpecialElements();
var removeOrUnwrapInvalidNode = function (node, originalNodeParent) {
if (originalNodeParent === void 0) {
originalNodeParent = node.parent;
}
if (specialElements[node.name]) {
node.empty().remove();
} else {
var children = node.children();
for (var _i = 0, children_1 = children; _i < children_1.length; _i++) {
var childNode_1 = children_1[_i];
if (!schema.isValidChild(originalNodeParent.name, childNode_1.name)) {
removeOrUnwrapInvalidNode(childNode_1, originalNodeParent);
}
}
node.unwrap();
}
};
for (ni = 0; ni < nodes.length; ni++) {
node = nodes[ni];
if (!node.parent || node.fixed) {
Expand All @@ -20706,31 +20742,35 @@
parents.push(parent);
}
if (parent && parents.length > 1) {
parents.reverse();
newParent = currentNode = filterNode(parents[0].clone());
for (i = 0; i < parents.length - 1; i++) {
if (schema.isValidChild(currentNode.name, parents[i].name)) {
tempNode = filterNode(parents[i].clone());
currentNode.append(tempNode);
if (schema.isValidChild(parent.name, node.name)) {
parents.reverse();
newParent = currentNode = filterNode(parents[0].clone());
for (i = 0; i < parents.length - 1; i++) {
if (schema.isValidChild(currentNode.name, parents[i].name)) {
tempNode = filterNode(parents[i].clone());
currentNode.append(tempNode);
} else {
tempNode = currentNode;
}
for (childNode = parents[i].firstChild; childNode && childNode !== parents[i + 1];) {
nextNode = childNode.next;
tempNode.append(childNode);
childNode = nextNode;
}
currentNode = tempNode;
}
if (!isEmpty$2(schema, nonEmptyElements, whitespaceElements, newParent)) {
parent.insert(newParent, parents[0], true);
parent.insert(node, newParent);
} else {
tempNode = currentNode;
parent.insert(node, parents[0], true);
}
for (childNode = parents[i].firstChild; childNode && childNode !== parents[i + 1];) {
nextNode = childNode.next;
tempNode.append(childNode);
childNode = nextNode;
parent = parents[0];
if (isEmpty$2(schema, nonEmptyElements, whitespaceElements, parent) || hasOnlyChild(parent, 'br')) {
parent.empty().remove();
}
currentNode = tempNode;
}
if (!isEmpty$2(schema, nonEmptyElements, whitespaceElements, newParent)) {
parent.insert(newParent, parents[0], true);
parent.insert(node, newParent);
} else {
parent.insert(node, parents[0], true);
}
parent = parents[0];
if (isEmpty$2(schema, nonEmptyElements, whitespaceElements, parent) || hasOnlyChild(parent, 'br')) {
parent.empty().remove();
removeOrUnwrapInvalidNode(node);
}
} else if (node.parent) {
if (node.name === 'li') {
Expand All @@ -20750,11 +20790,7 @@
if (schema.isValidChild(node.parent.name, 'div') && schema.isValidChild('div', node.name)) {
node.wrap(filterNode(new Node$1('div', 1)));
} else {
if (specialElements[node.name]) {
node.empty().remove();
} else {
node.unwrap();
}
removeOrUnwrapInvalidNode(node);
}
}
}
Expand Down Expand Up @@ -20930,6 +20966,7 @@
parser = SaxParser$1({
validate: validate,
allow_script_urls: settings.allow_script_urls,
allow_svg_data_urls: settings.allow_svg_data_urls,
allow_conditional_comments: settings.allow_conditional_comments,
self_closing_elements: cloneAndExcludeBlocks(schema.getSelfClosingElements()),
cdata: function (text) {
Expand Down
2 changes: 1 addition & 1 deletion thirdparty/tinymce/tinymce.min.js

Large diffs are not rendered by default.

0 comments on commit cafc1c4

Please sign in to comment.