# Content Security Policy

CKEditor 5 is compatible with applications that use [CSP rules](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) and helps developers build a secure web.

<a id="recommended-csp-configuration-for-cloud-deployments">

## Recommended CSP configuration for Cloud deployments

The recommended CSP configuration for [Cloud deployments](../licensing/usage-based-billing.md#cloud-hosted) that allows the rich-text editor to run out–of–the–box with all standard features using the content like images or media from external hosts looks as follows:

```
default-src 'none'; connect-src 'self'; script-src 'self' https://cdn.ckeditor.com https://proxy-event.ckeditor.com ; img-src * data:; style-src 'self' 'unsafe-inline'; frame-src *
```

<a id="recommended-csp-configuration-for-self-hosted-deployments">

## Recommended CSP configuration for self-hosted deployments

The recommended CSP configuration for self-hosted deployments (npm/ZIP) that allows the rich-text editor to run out–of–the–box with all standard features using the content like images or media from external hosts looks as follows:

```
default-src 'none'; connect-src 'self'; script-src 'self'; img-src * data:; style-src 'self' 'unsafe-inline'; frame-src *
```

<a id="impact-of-csp-on-editor-features">

## Impact of CSP on editor features

Some CSP directives have an impact on certain rich-text editor features. Here is the round-up of directives and their specific roles in the editor:

* `default-src 'none'`: Resets the policy and blocks everything. All successive directives work as a whitelist. By itself, as long as it is followed by other directives, it has no impact on the editor.

* `connect-src 'self'`

  * Allows the [editor upload features](../../features/images/image-upload/image-upload.md) to use [`XMLHttpReqests`](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) (Ajax) to upload files to the server, for instance, when an image is pasted or dropped into the editor content. The `'self`’ value ensures the requests remain within the same host.
  * Allows [auto–saving editor data](../../features/autosave.md) using `XMLHttpRequest`.

  **Note**: To use [CKEditor Cloud Services](https://ckeditor.com/ckeditor-cloud-services/), include the `http://*.cke-cs.com` domain in the `connect-src` directive, for instance: `connect-src 'self' http://*.cke-cs.com`.

* `script-src 'self'`: Allows the execution of JavaScript from the current host only and can be applied only if the CKEditor 5 script file (`<script src="[ckeditor-build-path]/ckeditor.js"></script>`) is also served from that host.

  **Note**: If CKEditor 5 is served from [Cloud](../licensing/usage-based-billing.md#cloud-hosted), make sure the value of `script-src` includes the required hosts, one for the CDN, and one for the [license check server](../licensing/usage-based-billing.md#license-check-and-usage-data): `script-src 'self' https://cdn.ckeditor.com https://proxy-event.ckeditor.com`.

* `img-src * data:`

  * The `*` directive value allows images in the editor content to come from any hosts.

  * The `data:` value allows:

    * Pasting [images from the clipboard](../../features/images/image-upload/image-upload.md) and [from MS Office](../../features/pasting/paste-from-office.md) into the editor content. Pasted images are usually represented as Base64–encoded strings (`<img src="data:..." />`) and without `data:` they cannot be displayed and uploaded.
    * Displaying the [media embed](../../features/media-embed/media-embed.md) feature placeholders for the inserted media.

  **Note**: Use the more strict `img-src 'self'` if all images in the editor content are hosted from the same domain and you do **not** want to enable the [media embed](../../features/media-embed/media-embed.md) and [paste from Word](../../features/pasting/paste-from-office.md) features.

* `style-src 'self' 'unsafe-inline'`:

  * The `self` directive allows to load styles from the site’s own domain. Since v42.0.0, the editor [distributes its stylesheets](content-styles.md). If you need to load styles from some other domain, add them explicitly: `style-src https://trusted-styles.example.com;`.
  * The directive `unsafe-inline` is required to make the styles of certain features work properly. For instance, you are going to need it if you want to enable such editor features as [font](../../features/font.md) or [text alignment](../../features/text-alignment.md) or any other feature that uses the inline `style="..."` attributes in the content.

  **Note**: Inline styles are also required when using [list item marker formatting](../../features/lists/lists-properties.md#list-item-marker-formatting). For example, if you apply font color, size, or family to list markers, the editor uses inline style attributes to render them. Because of this, `unsafe-inline` must be allowed for the styles to display correctly.

* `frame-src *`: Necessary for the [media embed](../../features/media-embed/media-embed.md) feature to load media with previews (containing `<iframe>`).

  **Note**: Use the more strict `frame-src 'self'` if all the media in the edited content come from the same domain as your application.

> **Note**
>
> A different set of Content Security Policy directives might be necessary to run [CKFinder](../../features/file-management/ckfinder.md) along with CKEditor 5. Check out the file manager [documentation](https://ckeditor.com/docs/ckfinder/ckfinder3/#!/guide/dev_integration-section-csp-directives-required-by-ckfinder) to learn more.

<a id="strictest-working-configuration">

## Strictest working configuration

Knowing the role of each directive, the strictest set of rules that allows CKEditor 5 to run is as follows:

```
default-src 'none'; connect-src 'self'; script-src 'self'; img-src 'self'; style-src 'self'; frame-src 'self'
```

This comes with some trade–offs, though. For example, it requires you to:

* Load images in the content from the same host.
* Load previewable media in the content from the same host.
* Give up certain features that use inline styles like [font](../../features/font.md) or [text alignment](../../features/text-alignment.md).
* Give up pasting images from the clipboard or [from Office](../../features/pasting/paste-from-office.md).

<a id="trusted-types">

## Trusted Types

[Trusted Types](https://developer.mozilla.org/en-US/docs/Web/API/Trusted_Types_API) is a browser mechanism against DOM-based XSS. It applies to DOM injection sinks: the properties and methods that turn a string into live HTML, such as `innerHTML`, `insertAdjacentHTML()` or `DOMParser#parseFromString()`. It also applies to attributes that run code or load a script, such as `onclick` or the `src` attribute of a `<script>` element. Under Trusted Types, a sink rejects a plain string and accepts only a value produced by a policy that the application allows.

CKEditor 5 supports running in applications that enforce Trusted Types. It creates its own policies and passes through them every value that it writes to a sink or to one of these attributes. Your application needs to allow the names of these policies, together with the policies of any third-party code that your setup includes.

<a id="enabling-trusted-types">

### Enabling Trusted Types

Add two directives to the Content Security Policy that your application sends:

```
require-trusted-types-for 'script'; trusted-types ckeditor5 ckeditor5-integrations lit-html;
```

The first directive turns the mechanism on. The second one lists the policy names that the browser allows. Add the names below to any that your application already lists. The `ckeditor5` name is always required, and the other two depend on your setup:

* `ckeditor5` – the policy of the editor.
* `ckeditor5-integrations` – a policy that the `useCKEditorCloud()` and `loadCKEditorCloud()` helpers create to inject the editor scripts. Add it whenever you [load the editor from CDN with these helpers](loading-cdn-resources.md), for example in the React, Vue.js 3+, or Angular integration.
* `lit-html` – a policy that the [Uploadcare](../../features/file-management/uploadcare.md) file uploader creates. It does not come from the editor. Add it whenever your build **contains** that feature. The ready-made premium features bundle always contains it, and the CDN helpers load that bundle when you set their [`premium` option](loading-cdn-resources.md#the-loadckeditorcloud-function-options) to `true`.

> **Warning**
>
> Under enforcement, the editor cannot recover from a refused policy, so it is never created. The console names the policy that was refused. What differs is when the failure happens and which code reports it.
>
> * Without `ckeditor5`, the failure happens as soon as the browser loads the editor’s code. The editor also logs the `trusted-types-policy-creation-failed` warning, because it creates that policy itself and catches the refusal.
> * Without `ckeditor5-integrations`, the failure happens before the browser loads the editor’s code. The CDN helpers also fail with the `TrustedTypesPolicyCreationError` error, because they create that policy themselves.
> * Without `lit-html`, the failure happens as soon as the browser loads the editor’s code. Only the browser reports it, because the editor does not create that policy and never sees the refusal.
>
> A policy is also refused when your application already created one with the same name, even though the name is listed. An application that uses Lit itself can hit this, because the premium features bundle brings its own copy. The same happens to `ckeditor5-integrations` when the page loads more than one copy of the `@ckeditor/ckeditor5-integrations-common` package. To allow the same name twice, add `'allow-duplicates'` to the `trusted-types` directive.

<a id="trusted-types-and-content-safety">

### Trusted Types and content safety

The policy of the editor returns every string unchanged. It makes the browser accept the markup and the attribute values that the editor writes, and it does not inspect, clean, or filter anything. Turning Trusted Types on therefore does not make the editor filter content, and the responsibility for the safety of the data loaded into the editor stays with your application, exactly as before.

This matters most for the [HTML embed](../../features/html/html-embed.md) feature. When it is configured to show previews, the browser runs whatever the embedded snippets contain. Trusted Types does not change that, and the [`config.htmlEmbed.sanitizeHtml`](../../api/module_html-embed_htmlembedconfig-HtmlEmbedConfig.md#member-sanitizeHtml) option remains the way to control it.

If you configure [General HTML Support](../../features/html/general-html-support.md) to allow event handler attributes, such as `onclick`, or `<script>` elements, the editor keeps them in the content. The policy passes these values through unchanged, like the HTML. As a result:

* The data that the editor returns contains them, exactly as without Trusted Types.
* Nothing runs while users edit the content, because the editing view renames such attributes and replaces `<script>` elements. The only exception is an attribute that your own converter explicitly allows.

To keep such content out of the editor, exclude it with the [`htmlSupport.disallow`](../../api/module_html-support_generalhtmlsupportconfig-GeneralHtmlSupportConfig.md#member-disallow) option.

<a id="detecting-trusted-types-enforcement">

### Detecting Trusted Types enforcement

To find out whether your application enforces Trusted Types, the editor writes to a sink once and checks whether the browser refuses the value. There is no other reliable way to tell.

The editor catches the refusal, but the browser still logs an error of its own and reports a CSP violation. In Chrome it reads `This document requires 'TrustedHTML' assignment`, and other browsers word it differently. This happens once per page, the first time the editor runs that check. **Nothing is broken by it.**

<a id="known-limitations">

### Known limitations

Four cases are affected when your application enforces Trusted Types. All four come from third-party code that writes HTML or attribute values the editor cannot route through its policy.

In the first two cases, the editor turns the feature off and logs a warning instead of letting it fail:

1. **The color picker**, everywhere it appears: [font color and font background color](../../features/font.md) and [table properties and table cell properties](../../features/tables/tables-styling.md). The color palettes and the document colors are not affected, so users keep every predefined color and lose only the custom ones. The editor logs `color-picker-unavailable-with-trusted-types` once for every color selector that it creates. To turn the picker off yourself and stop the warning, set the `colorPicker` option of each of those features to `false`.

2. **Parts of the file managers.**

   * **Uploadcare:** the dialog that the toolbar button opens and the image editor. Uploading files by pasting or dropping them keeps working. The editor logs `uploadcare-unavailable-with-trusted-types` once while it starts.
   * **CKBox:** the image editor. Choosing assets keeps working. The editor disables its **Edit image** button and logs `ckbox-image-edit-unavailable-with-trusted-types` once while it starts. The **Edit** button in the CKBox dialog is part of CKBox, so the editor cannot disable it: it opens the image editor, but the image never loads. When CKBox shows the thumbnail of a PDF file, the browser also reports a refused `Worker`. The thumbnail still renders.

The last two cases are different because they are errors on content rather than a feature switched off:

3. **Markdown that contains a named character reference**, such as `&nbsp;` or `&amp;`. Parsing such content fails, while Markdown without character references works. This affects every feature that parses Markdown, not only [Markdown output](../../features/markdown.md).
4. **Markdown with HTML that contains event handlers, external scripts, or inline frame content**, such as `<p onclick="...">`, `<script src="...">`, or `<iframe srcdoc="...">`. Parsing such content fails, while Markdown without them works. This affects [Markdown output](../../features/markdown.md) and [pasting Markdown](../../features/pasting/paste-markdown.md).

<a id="using-the-trustedhtml-helper">

### Using the `trustedHtml()` helper

To keep your own plugins and UI working under Trusted Types, pass the HTML they write to the DOM through the [`trustedHtml()`](../../api/module_utils_dom_trustedtypes.md#function-trustedHtml) helper, which is safe to call in any browser:

```js
import { trustedHtml } from 'ckeditor5';

element.innerHTML = trustedHtml( '<p>Hello world!</p>' );
```

> **Warning**
>
> `trustedHtml()` marks as trusted whatever it receives, and it checks nothing. Use it only for markup that your own code produced. Never pass it content that comes from a user, from a server response, or from any other outside source. Sanitize such content first.

---

Full index of the CKEditor 5 documentation: [llms.txt](../../../llms.txt)
