Content Security Policy (CSP) for sites built on Uniform

Last updated: July 14, 2026

Q: Do you provide a Content Security Policy and guidance for safely rendering delivered content?

A: Yes. Uniform-based sites should ship a standard Content-Security-Policy HTTP response header, applied to every route, that does three things:

  1. Restricts frame-ancestors to trusted origins only, including Uniform's own editor/preview origins, so the page can't be framed by arbitrary third-party sites while still allowing Uniform's visual editor to embed a live preview.

  2. Allowlists the outbound origins (connect-src) that content rendered through Uniform, and Uniform's own delivery/search services, are permitted to call.

  3. Leaves everything not explicitly required closed by default, rather than opening the policy broadly.

The values below are the actual directives used in a live Uniform implementation.

The header

A working policy looks like this (line-wrapped for readability; ship it as one header value):

Content-Security-Policy:
  connect-src 'self'
    *.uniform.global
    *.search.uniform.app
    <your own API, analytics, and third-party origins...>;
  frame-ancestors 'self'
    <https://uniform.app>

Set it as a standard security response header at whatever layer your framework or edge platform applies HTTP headers globally: a headers/middleware config, a reverse proxy, or a CDN rule. CSP is a plain HTTP header, not something tied to any particular framework.

Pair it with the usual complementary security headers, applied at the same layer:

Header

Recommended value

Purpose

X-Content-Type-Options

nosniff

Stops MIME-sniffing of delivered content.

Referrer-Policy

origin-when-cross-origin

Limits referrer leakage on outbound links.

Permissions-Policy

camera=(), microphone=()

Denies camera/mic to all rendered content, including anything delivered through Uniform.

Strict-Transport-Security

max-age=63072000; includeSubDomains; preload

Enforces HTTPS.

X-XSS-Protection

1; mode=block

Legacy browser XSS filter. CSP is the primary defense; this covers older browsers.

There's no need for an X-Frame-Options header. frame-ancestors is the modern, CSP-native replacement for it and is honored by all current browsers.

frame-ancestors: the embed/iframe control

frame-ancestors controls who is allowed to put your site in an <iframe>. This is the mechanism Uniform's visual editor (Canvas) depends on to render a live, click-to-edit preview of your page inside the editor UI. If your CSP doesn't allowlist Uniform's editor origins here, the in-context preview won't load.

The required Uniform origins:

  • https://uniform.app: the production and canary Canvas app origins

Include 'self' if the site needs to embed its own pages. Leave everything else out. Don't use a wildcard (*) in frame-ancestors, so third-party sites can't frame your pages for clickjacking.

Troubleshooting reference

if visual editing preview fails to load with a browser console error like:
Refused to frame '<https://yoursite.net/>' because an ancestor violates the following Content Security Policy directive: 'frame-ancestors ...'
add https://uniform.app to frame-ancestors. If a script-src directive is present, add https://uniform.app there too, since a locked-down script-src can block Canvas's preview runtime the same way an overly strict frame-ancestors does. See Uniform's troubleshooting guide, step 3, "Verify CSP allows embedding in an iframe":
https://docs.uniform.app/docs/guides/composition/visual-editing/troubleshoot-preview#3-verify-csp-allows-embedding-in-an-iframe

connect-src: allowlisting Uniform's services

connect-src governs which origins the page can make network calls to (fetch, XHR, WebSockets). It needs to include Uniform's delivery and search endpoints so client-side data fetching against Uniform isn't blocked:

  • .uniform.global: Uniform's content delivery / edge API

  • .search.uniform.app: Uniform's hosted search service (if in use)

Add your own site's other origins as needed: first-party APIs, analytics, forms, video, ad/martech vendors. Keep the list to what's actually integrated, not everything the site could conceivably use.

For teams that add new integrations often, one option is to manage this allowlist as content rather than code: store the directive as a plain-text field on a CMS-managed entry (for example a shared "site settings" or header composition in Uniform), and have the build pipeline fetch the published value and bake it into the response headers at build time. That lets marketing or growth add a new analytics or ad-pixel origin to connect-src by editing content and republishing, without a code deploy. frame-ancestors should stay hardcoded in application config rather than editable content, since it's a security boundary and belongs under code review.

Safe-rendering recommendations for delivered content

  • CSP limits what a successfully-injected script can call out to (connect-src) and who can frame the page (frame-ancestors). It doesn't replace sanitizing untrusted HTML or rich text coming from a CMS.

  • Render composition/component data through typed parameter mappings into your component tree, not by dumping raw strings into the DOM. Reserve raw HTML rendering (dangerouslySetInnerHTML in React, v-html in Vue) for specific rich-text fields, and only for content written by trusted, authenticated editors through the CMS, not for anything that could originate from an untrusted end user.

  • Uniform Canvas access is authenticated and authorized, so rich-text fields are a lower-risk surface than user-submitted content, but they're still HTML rendered into your page. CSP's connect-src/frame-ancestors restrictions are what limit the blast radius if that trust assumption is ever violated (a compromised editor account, a compromised rich-text plugin, and so on).

  • When a new integration needs a new CSP entry, add the specific origin required rather than widening a directive to a wildcard or dropping it.

Scope / known limitations

A minimal policy like the one above only defines connect-src and frame-ancestors. It doesn't restrict default-src, script-src, style-src, or img-src. That's a starting scope focused on network-call control and embedding control, not a claim that those other directives aren't worth adding. If you add a script-src directive, remember it also needs https://uniform.app allowlisted, or Canvas preview will break the same way it does with an overly strict frame-ancestors.