Skip to main content

Set up iframe protection

Set the Content Security Policy frame-ancestors directive on every route that renders HTML, so that your app can be framed only by the authenticated shop's admin, or by no one if your app isn't embedded.


Without a frame-ancestors directive, any site can load your app in a frame and overlay it to trick a user into clicking, which is clickjacking. Shopify rejects an app during App Store review if the directive is missing or set incorrectly, and you have to fix it before you resubmit.


Anchor to Apps rendered in the Shopify adminApps rendered in the Shopify admin

If your app is rendered in the Shopify admin, then set frame-ancestors to the authenticated shop's domain and https://admin.shopify.com. The value is different for every shop, and the header must be present on every route that renders HTML. For example, when the shop shopify-dev.myshopify.com renders your app, your response includes:

Content-Security-Policy: frame-ancestors https://shopify-dev.myshopify.com https://admin.shopify.com;

You can include other declarations in your Content-Security-Policy header besides frame-ancestors. Apps built from the React Router app template set these headers through shopify.addDocumentResponseHeaders in entry.server.tsx.

If your app isn't rendered in the Shopify admin, then set frame-ancestors to 'none' to disallow framing:

Content-Security-Policy: frame-ancestors 'none';

Anchor to Fix an app that's configured as embedded but isn'tFix an app that's configured as embedded but isn't

If your app isn't rendered in the Shopify admin, then its configuration must say so.

With Shopify CLI, set embedded = false in your shopify.app.toml file and release a new version with shopify app deploy:

embedded = false

In the Dev Dashboard, open your app, click Versions, then Create a version. In the URLs section, clear Embed app in Shopify admin, then click Release and confirm.

Anchor to Confirm the header on a live storeConfirm the header on a live store

  1. Log in to a store that has your app installed, and click Apps.
  2. Open your browser's developer tools and select the Network tab.
  3. Open your app. In the Network tab, click Doc to filter for document requests, and select the last document in the list.
  4. Confirm that the Request URL is on your app's domain, and that the response's Content-Security-Policy header includes a frame-ancestors directive for that store's domain.

The app security checks report an embedded app that omits frame-ancestors (MISSING_EMBEDDED_CSP) or sets it to a wildcard (STATIC_FRAME_ANCESTORS). The live-store check above confirms the per-shop value.


Was this page helpful?