How to set dynamic header for Content-Security-Policy: frame-ancestors

Hi, I’m using Netlify to host a Shopify app that is run inside an iframe in the Shopify dashboard. Shopify requires that I set the proper Content Security Policy frame-ancestors directive to avoid clickjacking attacks. The frame-ancestors header should be set dynamically to whatever shop origin has loaded the app. I read the _headers docs on Netlify and did some searching but couldn’t find anything if this is even possible. Others have accomplishes this by using middleware to set the CSP header unfortunately my app is a JavaScript SPA. Any help is greatly appreciated. Thanks!

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

Hey @philnetlify1,

Could you share the Netlify site URL?

Hi, @philnetlify1. To confirm, is this something you looking to solve programmatically because there are many shops being used so the subdomain cannot be known before hand?

If so, Edge Handlers would be a solution once they become publicly available. In the meantime, the only solution I see is to use a function to dynamically generate the headers.

Yes, you are correct. Basically I will need to programmatically validate the domain *.myshopify.com and then set the frame-ancestors to whichever shop domain is being used. The subdomain cannot be know before hand. I’ll look into functions. Thanks!

Hi @philnetlify1 Did you solve this? Can you share your functions file on how did you achieve this?
I have created a file in root-app-folder/.netlify/functions/index.js and this function never gets called.

Hi @srameshr

Functions are accessible via /.netlify/functions/<function-name> only after they are built.

The default directory for Netlify to automatically detect and build functions are per documentation is YOUR_BASE_DIRECTORY/netlify/functions.

Unless it is a function triggered on an event a function is never automatically called, you need to explicitly call it.

Can you please share your file on how you do this @philnetlify1

Even I am trying to set CSP for my embedded Shopify app

Hey @srameshr , I ended up switching over to Cloudflare Workers Sites. The following gist got me started configuring my web worker script. Some of it is probably applicable to Netlify function too. Hope it helps :slight_smile:

Just to clarify this is how I set my headers.

...
// return await getAssetFromKV(event, options);
const page = await getAssetFromKV(event, options);
const response = new Response(page.body, page);
response.headers.set("Content-Security-Policy", `frame-ancestors 'none'`);
const { searchParams } = new URL(event.request.url);
const shop = searchParams.get("shop");
if (shop !== null && shop.match(/^[a-zA-Z0-9][a-zA-Z0-9-]*\.myshopify\.com$/) !== null) {
  response.headers.set("Content-Security-Policy", `frame-ancestors https://${shop} https://admin.shopify.com`);
}

return response;

Yes, but how do we achieve this to set headers on Netlify functions? Functions wont be run on beforePageRequest right? They are just like API endpoints if you dont want to spin up your own API servers

Hey there folks! Just chiming in here to say we are working on a project that might make this possible in the future. I can’t share a timeline, but stay tuned!

As always, thanks for bringing great collaboration and great ideas to the Forums.

2 Likes