# Content Security Policy

> The CSP directives the ShopAssist widget needs, per platform, including Trusted Types and Cloudflare Turnstile.

Source: https://shopassist.coec.dk/docs/widget/content-security-policy · Updated 2026-10-01

If your store sends a `Content-Security-Policy` header, add these sources. The widget never needs `'unsafe-eval'` or `'unsafe-inline'`.

```text
script-src https://cdn.shopassist.coec.dk; connect-src https://api.shopassist.coec.dk https://cdn.shopassist.coec.dk; img-src https://cdn.shopassist.coec.dk <store media hosts> blob:; style-src https://cdn.shopassist.coec.dk
```

| Directive | Sources | Why |
| --- | --- | --- |
| `script-src` | `https://cdn.shopassist.coec.dk` | The loader and the chat app. Shopify serves the loader from the theme asset host; the app still needs our CDN. |
| `connect-src` | `https://api.shopassist.coec.dk https://cdn.shopassist.coec.dk` | The widget API, streamed replies (SSE over fetch), the analytics beacon, the signed manifest and language packs. |
| `img-src` | `https://cdn.shopassist.coec.dk <your store media hosts> blob:` | Avatars and logos from our CDN, product and store images from your own media hosts, blob: for photo previews and attachments. |
| `style-src` | `https://cdn.shopassist.coec.dk` | Only used when the browser cannot apply constructable stylesheets (older Safari). 'unsafe-inline' is never needed. |
| `trusted-types` | `shopassist` | Only when you enforce require-trusted-types-for 'script'. |

`<store media hosts>` are the hosts your product and store images come from (for example `cdn.shopify.com` or your own CDN).

## Trusted Types [#trusted-types]

If you enforce `require-trusted-types-for 'script'`, also add `trusted-types shopassist`. The widget creates exactly one policy, named `shopassist`, that only allows its own asset URLs.

## Cloudflare Turnstile [#turnstile]

If you enabled Turnstile for [bot protection](/docs/widget/bot-protection), add `https://challenges.cloudflare.com` to `script-src` and `frame-src`:

```text
script-src https://cdn.shopassist.coec.dk https://challenges.cloudflare.com; connect-src https://api.shopassist.coec.dk https://cdn.shopassist.coec.dk; img-src https://cdn.shopassist.coec.dk <store media hosts> blob:; style-src https://cdn.shopassist.coec.dk; frame-src https://challenges.cloudflare.com
```

| Directive | Sources | Why |
| --- | --- | --- |
| `script-src` | `https://cdn.shopassist.coec.dk` | The loader and the chat app. Shopify serves the loader from the theme asset host; the app still needs our CDN. |
| `connect-src` | `https://api.shopassist.coec.dk https://cdn.shopassist.coec.dk` | The widget API, streamed replies (SSE over fetch), the analytics beacon, the signed manifest and language packs. |
| `img-src` | `https://cdn.shopassist.coec.dk <your store media hosts> blob:` | Avatars and logos from our CDN, product and store images from your own media hosts, blob: for photo previews and attachments. |
| `style-src` | `https://cdn.shopassist.coec.dk` | Only used when the browser cannot apply constructable stylesheets (older Safari). 'unsafe-inline' is never needed. |
| `trusted-types` | `shopassist` | Only when you enforce require-trusted-types-for 'script'. |

## Not needed [#not-needed]

`unsafe-eval`, `unsafe-inline`, `font-src`, `worker-src`, `form-action`, `media-src`, and `frame-src` (except for Turnstile). Streamed replies use `fetch`, covered by `connect-src`.

## Per platform [#platforms]

* **Shopify:** the loader is served from your theme's asset host, which Shopify's CSP already allows; the app still needs `cdn.shopassist.coec.dk`.
* **Magento 2:** the module ships `etc/csp_whitelist.xml` with these hosts. Hyvä CSP themes work because the module renders no inline script.
* **WooCommerce and PrestaShop:** add the directives in your security-header plugin or server configuration.
* **Strict CSP or headless:** use the [SRI-pinned loader](/docs/widget/sri-pinned-loader).

Errors in the browser console: [CSP errors](/docs/troubleshooting/csp-errors).
