Christopher Townsend
Christopher Townsend

Reputation: 1746

Electron Content Security Policy error when connecting to my api

Creating a simple template electron app. I want to do a fetch request to my api but am continuously stopped by the Content Security Policy errors and I have no idea how to fix them.

Refused to connect to 'https://api.myapp.com/' because it violates the following Content Security Policy directive: "default-src 'self' 'unsafe-inline' data:". Note that 'connect-src' was not explicitly set, so 'default-src' is used as a fallback.

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Security-Policy" content="default-src 'self' 'unsafe-eval' ">
    <meta charset="UTF-8">
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>

app.js

 const handleSubmit = async () => {
    const response = await fetch("https://api.myapp.com/books", {
      method: "GET",
      headers: {
        "Content-Type": "application/json",
      },
    });
    return response.json();
  };

I have tried adding the api address to the existing policy, and adding additional policies but nothing works.

Upvotes: 22

Views: 24274

Answers (8)

Sasanka Weerakoon
Sasanka Weerakoon

Reputation: 416

if you are using electron forge update forge.config.js

Found a solution works for me in github

plugins: [
    [
      '@electron-forge/plugin-webpack',
      {
        devContentSecurityPolicy: `default-src * self blob: data: gap:; style-src * self 'unsafe-inline' blob: data: gap:; script-src * 'self' 'unsafe-eval' 'unsafe-inline' blob: data: gap:; object-src * 'self' blob: data: gap:; img-src * self 'unsafe-inline' blob: data: gap:; connect-src self * 'unsafe-inline' blob: data: gap:; frame-src * self blob: data: gap:;`,
        mainConfig: './webpack.main.config.js',
        renderer: {
          config: './webpack.renderer.config.js',
          entryPoints: [
            {
              html: './src/index.html',
              js: './src/renderer.ts',
              name: 'main_window',
              preload: {
                js: './src/preload.ts',
              },
            },
          ],
        },
      },
    ],
  ]

Upvotes: 0

45 - Tomas Avila
45 - Tomas Avila

Reputation: 1

just remove this part

<meta http-equiv="Content-Security-Policy" content="default-src 'self' 'unsafe-eval' ">

and what's related to that

Upvotes: 0

Hekuran Kokolli
Hekuran Kokolli

Reputation: 1

If you are using helmet() function for improving security in node js application then just edit the helmet middlewares with seting the directives of what external library you can use in this case as a script i set the self script and other scrips depending on the external libraries that was used:

app.use(
  app.use(helmet.contentSecurityPolicy({
    directives: {
      defaultSrc: ["'self'"],
      scriptSrc: ["'self'", 'https://unpkg.com'],
      connectSrc: ["'self'", 'https://reqres.in']
    }
  })
);

Upvotes: 0

Pranta Saha
Pranta Saha

Reputation: 771

Here in my case, HTML Meta was

<meta http-equiv="Content-Security-Policy" 
      content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe inline'" />

The Error that I was getting in my console

Refused to connect to 'http://127.0.0.1:8000/api/v1/categories' because it violates the following Content Security Policy directive: "default-src 'self'". Note that 'connect-src' was not explicitly set, so 'default-src' is used as a fallback.

So, as in error it is clearly mentioned that "default-src 'self'". That means by default source for everything will be self. It is also mentioned that I need to set "connect-src",

My Solution to this, just append this to your Content-Security-Policy Meta tag "connect-src http://localhost:* ws://localhost:*" you can set any url you need or even multiple url. Like: connect-src http://127.0.0.1:* ws://localhost:* https://myapiurl.dev

Here ws://localhost:* is needed for your code HMR you can replace * with your dev server port also.

<meta http-equiv="Content-Security-Policy" 
      content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe inline'; connect-src http://localhost:* ws://localhost:* " />

Upvotes: 4

Adarsh Jaiswal
Adarsh Jaiswal

Reputation: 105

Just remove the following line from your html code snippet:

<meta http-equiv="Content-Security-Policy" content="default-src 'self' 'unsafe-eval' ">

Upvotes: 1

Pedro Renan
Pedro Renan

Reputation: 121

If you are using forge.config.ts you can use:

plugins: [
    new WebpackPlugin({
      mainConfig,
      devContentSecurityPolicy: "connect-src 'self' * 'unsafe-eval'",
      renderer: {
        config: rendererConfig,
        entryPoints: [
          {
            html: './src/index.html',
            js: './src/index.tsx',
            name: 'main_window',
            preload: {
              js: './src/preload.ts',
            },
          },
        ],
      },
    }),
  ],
};

Upvotes: 12

Christopher Townsend
Christopher Townsend

Reputation: 1746

I found the answer to this. It seems that Webpack uses a default Content Security Policy for developer mode which can be overridden in the package.json.

Taken from webpack WebpackPluginRendererConfig

/**
     * Sets the [`Content-Security-Policy` header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy)
     * for the Webpack development server.
     *
     * Normally you would want to only specify this as a `<meta>` tag. However, in development mode,
     * the Webpack plugin uses the `devtool: eval-source-map` source map setting for efficiency
     * purposes. This requires the `'unsafe-eval'` source for the `script-src` directive that wouldn't
     * normally be recommended to use. If this value is set, make sure that you keep this
     * directive-source pair intact if you want to use source maps.
     *
     * Default: `default-src 'self' 'unsafe-inline' data:;`
     * `script-src 'self' 'unsafe-eval' 'unsafe-inline' data:`
     */
    devContentSecurityPolicy?: string;

By setting devContentSecurityPolicy in package.json I can set my own Content Security Policy.

"plugins": [
        [
          "@electron-forge/plugin-webpack",
          {
            "mainConfig": "./webpack.main.config.js",
            "devContentSecurityPolicy": "connect-src 'self' https://api.myapp.com 'unsafe-eval'",
            "renderer": {
              "config": "./webpack.renderer.config.js",
              "entryPoints": [
                {
                  "html": "./src/index.html",
                  "js": "./src/renderer.ts",
                  "name": "main_window"
                }
              ]
            }
          }
        ]
      ]

Note: Changing this and saving wont update the policy in the app. You need to stop and run 'npm start' again to apply these changes.

Upvotes: 23

granty
granty

Reputation: 8496

In the violation message you have a whitelist: Refused to connect to ... the following Content Security Policy directive: "default-src 'self' 'unsafe-inline' data:".

But in the meta tag you shown a different whitelist: default-src 'self' 'unsafe-eval'.

This means you have at least 2 CSPs in action. Several CSPs act as consistent filters - all sources intended to be allowed should pass all filters. As result a toughest rules from all CSP are applied.

Figure out where do you publish a first CSP and add connect-src https://api.myapp.com into it. And remove CSP in the meta tag.

Most likely it's some package publishes his default CSP via HTTP header (how to check), so the Helmet is under suspicion - it publishes default CSP since v4.
Of course you can publish CSP HTTP header directly with code like:

session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
  callback({ responseHeaders: Object.assign({
    ...details.responseHeaders,
    "Content-Security-Policy": [ "default-src 'self' 'unsafe-inline' data:" ]
    }, details.responseHeaders)});
  });

Upvotes: 6

Related Questions