Security guide

The following is general security advice that may be relevant to a website or application using TinyMCE.

Reporting TinyMCE security issues

Tiny values the work of security researchers in improving the security of technology products worldwide. We welcome researchers who wish to responsibly disclose vulnerabilities in our products or systems.

Note that we do not offer any “bug bounty” program or any form of payment for disclosed vulnerabilities.

To report a potential security vulnerability, contact our Security team at infosec@tiny.cloud.

In line with the United States National Infrastructure Advisory Council (NIAC) Vulnerability Disclosure Framework (PDF link), Tiny requests community members reporting potential security vulnerabilities maintain the confidentiality of their report and discovery until Tiny has investigated the issue and taken action to fix it.

Tiny will communicate with you regarding the status of your report and will, with your permission, publicly attribute the security issue’s discovery to you after the issue has been fixed and disclosed.

What we do to maintain security for TinyMCE

To protect TinyMCE users, Tiny:

  • Patches Cross-Site Scripting (XSS) vulnerabilities,

  • Keeps TinyMCE dependencies up to date, and

  • Provides information about how to configure a Content Security Policy that works with TinyMCE.

Scripts and XSS vulnerabilities

TinyMCE filters content such as scripts from the editor content, however, client-side applications can be by-passed by attackers. Tiny recommends processing received editor content through server-side filters.

SVGs (Scalable Vector Graphics) are not supported in TinyMCE to protect our users and their end-users. SVGs can be used to perform both client-side and server-side attacks.

From the 1st of January 2020, Security Advisories for patched XSS vulnerabilities will be published on the TinyMCE GitHub repository Security page.

Keeping dependencies up-to-date

To protect our users, Tiny ensures that the TinyMCE dependencies are updated before the next version (major or minor) is released.

Configuring Content Security Policy (CSP) for TinyMCE

TinyMCE can be used with a CSP header. When using a CSP, the following directives are required for TinyMCE to function:

Policy directives Reason

script-src 'self' *.tinymce.com *.tiny.cloud;

Scripts are sometimes loaded as script element with an src attribute.

connect-src 'self' *.tinymce.com *.tiny.cloud blob:;

XMLHttpRequest is required by some services such as spellchecking and PowerPaste.

img-src 'self' *.tinymce.com *.tiny.cloud data: blob:;

Images within the editor are sometimes base64 encoded, blob URLs, or proxied through the Tiny Cloud service.

style-src 'self' 'unsafe-inline' *.tinymce.com *.tiny.cloud;

Styles are used for inline formatting (such as underline, font colors, etc.) and the positioning of user interface elements.

font-src 'self' *.tinymce.com *.tiny.cloud;

Fonts are used for icons in the UI and is loaded from external files.

There is a hardened approach to CSP, commonly known as strict CSP. A strict CSP:

  1. uses a nonce for all <script> elements;

  2. regenerates each nonce on every page load;

  3. refactors inline event handlers such that they are added from a JavaScript block; and

  4. does not allow the unsafe-inline value in any directive.

However, TinyMCE currently requires the unsafe-inline value in the style-src directive to present content other than plain-text.

As a consequence, running TinyMCE from within a strict CSP configuration is not currently supported.

Also, the required directives documented above prevent any content loading from external sources. To allow content from specific sources, add the source domains to the relevant directives. For example, to allow YouTube videos:

media-src 'self' *.youtube.com;

To allow content from any source, use the (*) wildcard. Allowing all sources (using *) negates the security policy for the source type. For example:

media-src *;

For information on Content Security Policies, see: MDN Web Docs - Content Security Policy (CSP).

When using the Tiny Cloud, use this CSP header:

<meta
  http-equiv="Content-Security-Policy"
  content="default-src 'none'; script-src 'self' *.tinymce.com *.tiny.cloud; connect-src 'self' *.tinymce.com *.tiny.cloud blob:; img-src 'self' *.tinymce.com *.tiny.cloud data: blob:; style-src 'self' 'unsafe-inline' *.tinymce.com *.tiny.cloud; font-src 'self' *.tinymce.com *.tiny.cloud;"
>

When self-hosting TinyMCE from a local domain, use this CSP header (excludes the *.tiny.cloud domain):

<meta
  http-equiv="Content-Security-Policy"
  content="default-src 'none'; script-src 'self'; connect-src 'self' blob:; img-src 'self' data: blob:; style-src 'self' 'unsafe-inline'; font-src 'self';"
>

General security risks for user input elements

The following security risks are not TinyMCE specific, but are the main security risks associated with websites or applications which allow user inputs. Protecting your services and users from these risks requires server-side handling. Note that attackers will likely bypass any editor and attack the server directly, rather than use the text editor as a vector.

For information on mitigating these risks, see the provided links in each section.

Cross-Site Scripting (XSS)

Cross-Site Scripting (XSS) involves using website or application inputs to inject malicious, client-side code. This code can then be used to attack your users.

Although TinyMCE filters content such as scripts from the editor content, precautions should be taken to protect your users, such as enabling a Content Security Policy (CSP) and server-side filtering.

For information on Cross-Site Scripting and how to reduce the risk of an attack, see: OWASP Top Ten 2017 — Cross-Site Scripting (XSS).

Injection

Injection attacks involve attackers using website or application inputs to run server-side code, such as SQL, NoSQL, or LDAP scripts.

If user inputs are not properly sanitized server-side, host devices and user data can be compromised.

For information on Injection-related security issues and how to reduce the risk of an attack, see: OWASP Top Ten 2017 — Injection.

Sanitizing HTML input to protect against XSS attacks

Previously, before HTML content was passed to TinyMCE 5.x, it was parsed using an in-house developed API, SaxParser.

The SaxParser API was developed in the then-absence of alternatives.

When this API’s validate setting was enabled — validate: trueSaxParser removed elements and attributes that did not fit the declared schema.

And, over its lifetime, SaxParser was extended. For example, as of TinyMCE 5.9, the SaxParser API marked attributes with certain names or IDs as unsafe, because some names or IDs can cause the host browser to overwrite existing properties or functions.

For TinyMCE 6.0, however, this basic parser was removed and replaced with two significantly more thorough alternatives:

  1. the native browser API, DOMParser(); and

  2. the Free and Open Source XSS sanitizer for HTML, MathML and SVG, DOMPurify.

TinyMCE uses DOMPurify 2.x, which was current at the time version 6 was developed.

Before HTML (or XML) content is passed to TinyMCE 6.x, the DOMParser API parses the HTML (or XML) string into a DOM object. As part of this process, DOMParser attempts to correct malformed HTML.

For example, the following string:

<p>
<a href="https://example.com">Click here.
</p>

When this string is passed in, the DOMParser API adds the missing closing anchor tag:

<p>
<a href="https://example.com">Click here.</a>
</p>

Next, the, now correctly formed, DOM object is passed to DOMPurify.

DOMPurify runs a security-focused ruleset over the DOM object to sanitize the HTML and protect TinyMCE, and applications using TinyMCE, against XSS attacks.

Turning DOMPurify off

DOMPurify sanitization is on by default, and prior to TinyMCE 6.4, it could not be turned off.

As of TinyMCE 6.4, however, it is possible to turn DOMPurify off using the xss_sanitization option.

xss_sanitization is set to true by default. That is, TinyMCE specifically sets the xss_sanitization option to true, even if this option is not declared in a TinyMCE configuration.

Type: Boolean

Default value: true

Possible values: true, false

Example: using xss_sanitization to turn DOMPurify off and no longer sanitize HTML against XSS attacks
tinymce.init({
  selector: 'textarea',  // change this value according to your HTML
  xss_sanitization: false
});
Turning DomPurify off leaves TinyMCE, and any application using TinyMCE, extremely vulnerable to XSS attacks. Only turn DomPurify off if alternative and equivalently capable HTML and XML sanitization and XSS protections are in place.

Securing embedded external resources

sandbox_iframes option

This option controls whether the editor will add a sandbox="" attribute to all <iframe> elements. This will restrict the iframe’s embedded resource from performing potentially malicious actions including scripting, file downloads, browser popups, passing the same-origin policy, among others. Reference: MDN.

Type: Boolean

Possible values: true, false

Default value: false

Example: using sandbox_iframes option
tinymce.init({
  selector: 'textarea',  // change this value according to your html
  sandbox_iframes: true
});

convert_unsafe_embeds option

This option controls whether an <object> and <embed> elements will be converted to more restrictive alternatives, namely <img> for image MIME types, <video> for video MIME types, <audio> for audio MIME types, or <iframe> for other or unspecified MIME types.

When converted to <img>, <video>, or <audio>, this prevents the embedded resource from performing potentially malicious actions including scripting, file downloads, browser popups, passing the same-origin policy, among others. Enable the sandbox_iframes option in addition to ensure <iframe> conversions are also neutralised.

Type: Boolean

Possible values: true, false

Default value: false

Example: using convert_unsafe_embeds option
tinymce.init({
  selector: 'textarea',  // change this value according to your html
  convert_unsafe_embeds: true
});

Insecure Transmission and Storage of data

The transmission or storage of data without strong cryptographic protection leaves this content exposed to attackers.

Loading insecure content into the editor, or submitting content from the editor over an insecure connection exposes the user and the host server to attack.

For information on Sensitive Data Exposure issues and how to reduce the risk of an attack, see: OWASP Top Ten 2017 — Sensitive Data Exposure.

Broken Authentication and Session Management

Broken or incorrectly implemented authentication and session management exposes both user data and the server to attackers, allowing them to impersonate users, including administrators.

Broken Authentication or session management may allow attackers to change or submit data through the editor, or any input field, as the compromised user account.

For information on Broken Authentication issues and how to reduce the risk of an attack, see: OWASP Top Ten 2017 — Broken Authentication.

Using Components with Known Vulnerabilities

Using outdated components on your website or application allows attackers to exploit known vulnerabilities.

TinyMCE is patched when vulnerabilities are discovered. Keeping TinyMCE and your other dependencies up to date will protect you and your users from known vulnerabilities.

For information on issues related to using components with known issues and how to reduce the risk of an attack, see: OWASP Top Ten 2017 — Using Components with Known Vulnerabilities.

Further security information

For general security advice about securing your website or application, visit the Open Web Application Security Project (OWASP).