Search code examples
javascriptnext.jsamp-htmlcontent-security-policy

Problem with Content-Security-Policy, Next JS and AMP


I am developing an AMP application using Next JS, it is working great in localhost, but in production I have errors coming from AMP that is not allowed to load its workers.

The initial error is :

Refused to create a worker from 'blob:' because it violates the following Content Security Policy directive: "default-src * data: 'unsafe-eval' 'unsafe-inline'". Note that 'worker-src' was not explicitly set, so 'default-src' is used as a fallback.

Ok I understand this error, I can see the header sent by next JS by default is default-src * data: 'unsafe-eval' 'unsafe-inline' and it doesn't allow blob: to be loaded, so the browser is refusing to load AMP's scripts.

So I add an header in next.config.js (I am using next 9.5 which has this new feature) to allow blob for workers :

async function headers() {
  return [
    {
      source: "/",
      headers: [
        {
          key: "Content-Security-Policy",
          value: "default-src * data:  'unsafe-eval' 'unsafe-inline'; worker-src blob:;",
        },
      ],
    }
  ];
}

With this configuration, I can see the header is correctly added in the response, but now there are two headers, nextJS is still sending his header by default :

enter image description here

So now I have two headers in the response, the first one is mine and defines worker-src, the second one is the next JS default one and doesn't define worker-src.
I would expect the browser to understand it but it doesn't work, I still have the same error, the browser doesn't pick up my worker-src policy.

Note: I can't use tag <meta http-esquiv="content-security-policy" /> because it is not valid AMP.

Note 2 : The workers are loaded only by some AMP components, I think the main ones are amp-bind and amp-script. With a lot of components I don't have this problem.

Does anyone have a solution for this ?

Thank you very much for reading.


Solution

  • With multiple CSPs the browser will only allow what is allowed in ALL CSPs. The default next JS CSP will block blob even though your custom CSP allows it. You will probably need to remove one of the CSPs and modify the other to suit your needs.

    See also "Multiple content security policies" section in https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy