Electron Content Security Policy error when connecting to my api
Asked Answered
A

8

21

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.

Appropriate answered 27/11, 2021 at 5:32 Comment(0)
A
22

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.

Appropriate answered 27/11, 2021 at 17:57 Comment(1)
to get my electron app talking to my localhost server I did: "devContentSecurityPolicy": "default-src 'self' 'unsafe-eval' 'unsafe-inline' http://localhost:* ws://localhost:*;",Coccidioidomycosis
O
12

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',
            },
          },
        ],
      },
    }),
  ],
};
Over answered 11/1, 2023 at 21:29 Comment(0)
T
6

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)});
  });
Terresaterrestrial answered 27/11, 2021 at 8:29 Comment(1)
Thanks so much for this response, it helped me track down the additional content security policy.Appropriate
C
3

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:* " />
Crenel answered 13/3, 2023 at 13:50 Comment(0)
C
1

Just remove the following line from your html code snippet:

<meta http-equiv="Content-Security-Policy" content="default-src 'self' 'unsafe-eval' ">
Crosspurpose answered 11/2, 2023 at 6:47 Comment(1)
You will need to explain why this line was the culprit.Boethius
P
0

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']
    }
  })
);
Percaline answered 2/9, 2023 at 19:9 Comment(0)
T
0

just remove this part

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

and what's related to that

Trike answered 4/12, 2023 at 15:14 Comment(0)
C
0

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',
              },
            },
          ],
        },
      },
    ],
  ]
Christianson answered 29/5, 2024 at 5:31 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.