Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not loading due to Content Security Policy Directive on CDN requests #1283

Open
2 of 7 tasks
tconroy opened this issue Oct 4, 2020 · 26 comments
Open
2 of 7 tasks

Not loading due to Content Security Policy Directive on CDN requests #1283

tconroy opened this issue Oct 4, 2020 · 26 comments

Comments

@tconroy
Copy link

tconroy commented Oct 4, 2020

This issue pertains to the following package(s):

  • GraphQL Playground - Electron App
  • GraphQL Playground HTML
  • GraphQL Playground
  • GraphQL Playground Express Middleware
  • GraphQL Playground Hapi Middleware
  • GraphQL Playground Koa Middleware
  • GraphQL Playground Lambda Middleware

What OS and OS version are you experiencing the issue(s) on?

MacOS 10.15.6 (Catalina), all browsers.

What version of graphql-playground(-electron/-middleware) are you experiencing the issue(s) on?

latest

What is the expected behavior?

I would expect to load the GraphQL playground.

What is the actual behavior?

Stuck at "Loading GraphQL Playground" screen with the following errors in console:

Refused to load the image 'http://cdn.jsdelivr.net/npm/@apollographql/graphql-playground-react@1.7.33/build/favicon.png' because it violates the following Content Security Policy directive: "img-src 'self' data:".

graphql:1 Refused to load the script 'https://cdn.jsdelivr.net/npm/@apollographql/graphql-playground-react@1.7.33/build/static/js/middleware.js' because it violates the following Content Security Policy directive: "script-src 'self'". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.

graphql:531 Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-PT+YOJyhu3IamY7Pf1cnvQbDxlHIK2FjqtA7GQoyN5U='), or a nonce ('nonce-...') is required to enable inline execution.

graphql:1 Refused to load the image 'https://cdn.jsdelivr.net/npm/@apollographql/graphql-playground-react@1.7.33/build/favicon.png' because it violates the following Content Security Policy directive: "img-src 'self' data:".

What steps may we take to reproduce the behavior?

Attempt to visit graphql-playground.

Please provide a gif or image of the issue for a quicker response/fix.
image

@bke-daniel
Copy link

@tconroy I could get rid of a view errors with passing these options:

const playground: PlaygroundConfig = {
  cdnUrl: 'https://cdn.jsdelivr.net/npm',
  faviconUrl: '',
};

The two errors related to index.css and middleware.js still remain.

    //...
    "apollo-server-core": "^2.18.1",
    "apollo-server-express": "^2.18.1",
    "express": "^4.17.1",
    "graphql": "^15.3.0",
    "graphql-tools": "^6.2.3",

@CatsMiaow
Copy link

I had the same problem and solved it.
This is a problem with setting the "Content-Security-Policy" header value that the web server responds.
image
need to delete or modify the setting.

In my case, the helmet module was responding, and I solved it by modifying it as follows.

app.use(helmet({ contentSecurityPolicy: (process.env.NODE_ENV === 'production') ? undefined : false }));

@tconroy
Copy link
Author

tconroy commented Oct 5, 2020

Ah, brilliant! That was the same case as me @CatsMiaow -- was using a boilerplate and wasn't aware of the Helmet config. The value you set works perfectly. Thank you for the help!

@pavellishin
Copy link

pavellishin commented Oct 21, 2020

Where does the helmet config live? I've had a similar issue open for over a year (#1069) and I have no idea where to make this modification. I have no idea what helmet even is; the playground in my case is bundled with ... I'm not even sure, to be honest. Presumably one of these:

    "@apollo/gateway": "^0.6.13",
    "apollo-datasource-rest": "^0.5.0",
    "apollo-server": "^2.9.5",
    "apollo-server-testing": "^2.8.0",

@alex-r89
Copy link

alex-r89 commented Nov 8, 2020

I had the same problem and solved it.
This is a problem with setting the "Content-Security-Policy" header value that the web server responds.
image
need to delete or modify the setting.

In my case, the helmet module was responding, and I solved it by modifying it as follows.

app.use(helmet({ contentSecurityPolicy: (process.env.NODE_ENV === 'production') ? undefined : false }));

Is there any issue in setting contentSecurityPolicy to undefined in production?

@CatsMiaow
Copy link

https://github.com/helmetjs/helmet/blob/d491d281eb1cc55380046532d24fbc314af836e0/index.ts#L69-L75
undefined is the default. When undefined, it is enabled as the default option.

@zsolt-dev
Copy link

Disabling contentSecurityPolicy for development is not the best idea, since developers will not notice something does not work until it's in the production.

I think the graphql playground should have all the scripts as npm development dependencies and not hosted on cdn.jsdelivr.net.

Another solution is whitelisting cdn.jsdelivr.net in CSP, but it is not a good idea, since anyone can upload anything on jsdelivr.net, which makes the CSP useless.

@tlenex
Copy link

tlenex commented Nov 8, 2021

This should be reopened.
The root of issue lays in insecure playground implementation - this should be addressed based on issues reported by CSP checks.
Like get rid of all inline scripts/styles/fonts/images and use whitelisted domain only or locally served files.
Then it should be simple to configure helmet without using insecure directives/options.

@acao acao reopened this Nov 8, 2021
@pavellishin
Copy link

Like get rid of all inline scripts/styles/fonts/images and use whitelisted domain only or locally served files.

I'm only tangentially familiar with this particular issue, but why not use inline styles and other assets for the gql playground? This would also make it functional when offline, and as far as I'm aware, the playground is typically used for development, not for users in production.

@tlenex
Copy link

tlenex commented Nov 8, 2021

Well you don't want to disable CSP headers for development envs, because you will miss other issues with it, up until production, on your API.
Therefore your playground is not working anyway or you introduce security issue with header policies to the whole app or you waste some resources and create a separate app with different header policy just for playground.
The issue is even more serious if you plan to use playground as public and open API tool.

The other approach for this might be generating proper exclusions for CSP headers, I think.

@Ismaestro
Copy link

Ismaestro commented Nov 29, 2021

And what about the opposite? @zsolt-dev

const appConfig = app.get(AppConfigService);
app.use(helmet({ contentSecurityPolicy: (appConfig.environment === 'localhost') ? false : undefined }));

That way we have enabled CSP in other environments but localhost...

PD: yes this only works if you don't want to publish the playground...

@kweij
Copy link

kweij commented Jan 14, 2022

For those of you running into this after upgrading helmet to v5 or higher (as I did), you will also get a console error and blocked response because of COEP/CORP headers (in Chrome, but not in Firefox). This happens because the initial request to cdn.jsdelivr.com yields a 307 Temporary Redirect from http to https (because of the HSTS configuration on the jsdelivr side). This redirect itself does not contain the proper CORP headers -- I think.

I have addressed this at jsdelivr's repo: jsdelivr/jsdelivr#18201 (comment)

To circumvent this, also disable the crossOriginEmbedderPolicy header:

  app.use(helmet({ contentSecurityPolicy: false, crossOriginEmbedderPolicy: false }))

@ramayac
Copy link

ramayac commented Jan 14, 2022

@kweij you're the hero of the day, thanks for taking the time to add this precise comment, thanks!!!

@AhmedBHameed
Copy link

AhmedBHameed commented Jan 15, 2022

@bke-daniel
Your suggestion solved my issue. Thanks!

@kweij
Copy link

kweij commented Jan 17, 2022

I have filed a bug at Chrome for this (the COEP / CORP headers) issue, as it seems that this is not the way the browser should handle this (i.e.: HSTS redirects should be internal to the browser and not expect CORP headers):

https://bugs.chromium.org/p/chromium/issues/detail?id=1287500

EDIT: A fix has been made Jan 19, 2022 👍

@AnimeshRy
Copy link

AnimeshRy commented Mar 4, 2022

I'm facing this currently, localhost:4000/graphql was working fine an hour back and now it's gone down. First the request took a long time to fetch and then when I reinstalled all of my modules, the apollo server doesn't even run

@jensbodal
Copy link

If you want to still have CSP headers but limit it somewhat (instead of disabling entirely)

  const devContentSecurityPolicy = {
    directives: {
      scriptSrc: ["'self'", "'unsafe-inline'", 'https://cdn.jsdelivr.net'],
      imgSrc: ["'self'", 'data:', 'https://cdn.jsdelivr.net'],
    },
  };

  app.use(
    helmet({
      // when undefined it will load the default option: https://github.com/graphql/graphql-playground/issues/1283#issuecomment-723705276
      contentSecurityPolicy: IS_DEV ? devContentSecurityPolicy : undefined,
    }),
  );

@kolpaja
Copy link

kolpaja commented Aug 10, 2022

I had the same problem and solved it. This is a problem with setting the "Content-Security-Policy" header value that the web server responds. image need to delete or modify the setting.

In my case, the helmet module was responding, and I solved it by modifying it as follows.

app.use(helmet({ contentSecurityPolicy: (process.env.NODE_ENV === 'production') ? undefined : false }));

Thanks you so much, I was trying to setup the graphql playground but it stayed at the loading..., until I google for a some minutes I came across of this post. thanks

@JiggyJinjo
Copy link

Correct me if I'm wrong but this issue is still ongoing as there is no current fix for production Open APIs serving this playground.

@krisgardiner
Copy link

Adding headers to ApolloServerPluginLandingPageLocalDefault options worked for me.
Versions:

"@apollo/server": "^4.0.3",
"@apollo/server-plugin-landing-page-graphql-playground": "^4.0.0",
ApolloServerPluginLandingPageLocalDefault({
   headers: {
      "Content-Security-Policy": "default-src 'self' https://apollo-server-landing-page.cdn.apollographql.com;",
   },
}),

@tobiasschweizer
Copy link

Adding headers to ApolloServerPluginLandingPageLocalDefault options worked for me. Versions:

"@apollo/server": "^4.0.3",
"@apollo/server-plugin-landing-page-graphql-playground": "^4.0.0",
ApolloServerPluginLandingPageLocalDefault({
   headers: {
      "Content-Security-Policy": "default-src 'self' https://apollo-server-landing-page.cdn.apollographql.com;",
   },
}),

Unfortunately, this does not work for me. Maybe I need to define different settings?

Refused to load the image 'https://apollo-server-landing-page.cdn.apollographql.com/_latest/assets/favicon.png' because it violates the following Content Security Policy directive: "img-src 'self' data:".

graphql:22 Refused to load the image 'https://apollo-server-landing-page.cdn.apollographql.com/_latest/assets/favicon.png' because it violates the following Content Security Policy directive: "img-src 'self' data:".

graphql:1 Refused to load the script 'https://embeddable-sandbox.cdn.apollographql.com/_latest/embeddable-sandbox.umd.production.min.js?runtime=%40apollo%2Fserver%404.7.4' because it violates the following Content Security Policy directive: "script-src 'self'". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.

graphql:71 Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-OK7pAH5PWuMz0B3Z+8KJD+AVvhgLxb2X4W00TmJw2M8='), or a nonce ('nonce-...') is required to enable inline execution.

Refused to load the image 'https://apollo-server-landing-page.cdn.apollographql.com/_latest/assets/favicon.png' because it violates the following Content Security Policy directive: "img-src 'self' data:".

graphql:1 Refused to load manifest from 'https://apollo-server-landing-page.cdn.apollographql.com/_latest/manifest.json' because it violates the following Content Security Policy directive: "default-src 'self' Note that 'manifest-src' was not explicitly set, so 'default-src' is used as a fallback.

Any hint is appreciated!

@tobiasschweizer
Copy link

@krisgardiner Are you still using the same setup? I saw "@apollo/server-plugin-landing-page-graphql-playground" is now deprecated.

My setup is now as in https://docs.nestjs.com/graphql/quick-start#apollo-sandbox, but it does not work.

The HTML source looks as follows:

<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'nonce-b5693f538f65c3b4938853dfcf85ff99c16ab6ef4dc5341e87b0c69ccbafa012' https://apollo-server-landing-page.cdn.apollographql.com https://embeddable-sandbox.cdn.apollographql.com https://embeddable-explorer.cdn.apollographql.com; style-src 'nonce-b5693f538f65c3b4938853dfcf85ff99c16ab6ef4dc5341e87b0c69ccbafa012' https://apollo-server-landing-page.cdn.apollographql.com https://embeddable-sandbox.cdn.apollographql.com https://embeddable-explorer.cdn.apollographql.com https://fonts.googleapis.com; img-src https://apollo-server-landing-page.cdn.apollographql.com; manifest-src https://apollo-server-landing-page.cdn.apollographql.com; frame-src https://explorer.embed.apollographql.com https://sandbox.embed.apollographql.com https://embed.apollo.local:3000" />
 
...

<script nonce="b5693f538f65c3b4938853dfcf85ff99c16ab6ef4dc5341e87b0c69ccbafa012">

  var initialEndpoint = window.location.href;
  var embeddedSandboxConfig = {"target":"#embeddableSandbox","initialState":{"headers":{"Content-Security-Policy":"default-src \u0027self' https://apollo-server-landing-page.cdn.apollographql.com;"}},"hideCookieToggle":false,"endpointIsEditable":false,"runtime":"@apollo/server@4.7.5","runTelemetry":true,"allowDynamicStyles":false};
  new window.EmbeddedSandbox(
   {
   ...embeddedSandboxConfig,
   initialEndpoint,
   }
   );
   </script>

@tobiasschweizer
Copy link

It was a config issue with content security policy, see https://docs.nestjs.com/security/helmet

@acao
Copy link
Member

acao commented Jul 8, 2023

for anyone who might be interested, here is an example of how to load the new graphiql as an apollo server plugin:

https://codesandbox.io/p/sandbox/apollo-server-w-graphiql-8xbnju

we are pushing forward on adding the monaco-graphql mode that I created as well for 4.0.0

@johnson-elugbadebo
Copy link

I just spent a good 2 days of my life that I will never get back trying to figure this out -- the config in the nestjs docs worked beautifully. Thank you!

@saegeullee
Copy link

@johnson-elugbadebo oh man thanks this works so fine!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests