SecurityError: The operation is insecure. Content Security Policy directive: "default-src 'self'"

I am generated an app with Phoenix 1.6.9 and when I tried to test on the safari browser 15.3 version. But on the brave, firefox, chrome is ok
It’s like the app is loading and re-loading again and again.
I inspect the console and complains for this:

Refused to connect to ws://localhost:4000/live/websocket?_csrf_token=bEogRCU3Vh8iECQ2LTc0OQU1cTRPAARb-8kqNn4ZQDEczXqktbFRbie0&_track_static%5B0%5D=http%3A%2F%2Flocalhost%3A4000%2Fassets%2Fapp.css&_track_static%5B1%5D=http%3A%2F%2Flocalhost%3A4000%2Fassets%2Fapp.js&_mounts=0&vsn=2.0.0 because it appears in neither the connect-src directive nor the default-src directive of the Content Security Policy.

[Error] SecurityError: The operation is insecure.
	(função anônima) (app.js:931)
	connect (app.js:931)
	doConnect (app.js:4370)
	connect (app.js:4374)
	(função anônima) (app.js:5005)
	Código Global (app.js:5007)

And I am trying to have fonts from google fonts by link:

root.html.heex

    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700&display=swap" rel="stylesheet">

app.css

body {
  font-family: 'Roboto', sans-serif;
  --webkit-font-smoothing: antialiased;
  color: var(--dark);
}

But it’s not showing the robot font style.

It’s complaining on the brave and firefox browsers this:

localhost/:1 Refused to load the image 'data:image/svg+xml;base64,PHN2ZyBpZD0ic291cmNlIiB3aWR0aD0iMjIiIGhlaWdodD0iMjIiIHZpZXdCb3g9IjAgMCAyMiAyMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGNpcmNsZSBjeD0iMTEiIGN5PSIxMSIgcj0iMTEiIGZpbGw9ImJsYWNrIiBmaWxsLW9wYWNpdHk9IjAuOCI+PC9jaXJjbGU+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTUuMDgzNCA0LjU4MzMzSDEzLjMzMzRWNS43NDk5OUgxNS4wODM0QzE1LjcyNjggNS43NDk5OSAxNi4yNSA2LjI3MzI0IDE2LjI1IDYuOTE2NjZWOC42NjY2NkgxNy40MTY3VjYuOTE2NjZDMTcuNDE2NyA1LjYyOTgzIDE2LjM3MDIgN...U4NTIgMTMuOTAyMSAxNC41ODUyIDEzLjM0NzkgMTQuMjQ0IDEzLjAwNjFMMTMuMDcwMyAxMS44MzNDMTMuMjM0MiAxMS40OTA2IDEzLjMzMzQgMTEuMTEyNiAxMy4zMzM0IDEwLjcwODNDMTMuMzMzNCA5LjI2MTA4IDEyLjE1NTYgOC4wODMzMyAxMC43MDg0IDguMDgzMzNDOS4yNjExMiA4LjA4MzMzIDguMDgzMzcgOS4yNjEwOCA4LjA4MzM3IDEwLjcwODNDOC4wODMzNyAxMi4xNTU2IDkuMjYxMTIgMTMuMzMzMyAxMC43MDg0IDEzLjMzMzNDMTEuMTEyNiAxMy4zMzMzIDExLjQ5MDYgMTMuMjM0MiAxMS44MzMgMTMuMDcwMkwxMy4wMDYxIDE0LjI0MzlDMTMuMTc3IDE0LjQxNDggMTMuNDAxIDE0LjUgMTMuNjI1IDE0LjVaIiBmaWxsPSJ3aGl0ZSI+PC9wYXRoPgo8L3N2Zz4=' because it violates the following Content Security Policy directive: "default-src 'self'". Note that 'img-src' was not explicitly set, so 'default-src' is used as a fallback.

localhost/:1 Refused to load the stylesheet 'https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700&display=swap' because it violates the following Content Security Policy directive: "default-src 'self'". Note that 'style-src-elem' was not explicitly set, so 'default-src' is used as a fallback.

Refused to load the font 'data:font/truetype;charset=utf-8;base64, d09GRgABAAAAAMjjABIAAAAB2mAAAAAAAADH7AAAAPcAAAHiAAAAAAAAAABHUE9TAACdfAAAIjcAAH80VqR1REdTVUIAAL+0AAAINwAAFD6g7KTPTFRTSAAABwQAAABHAAACQYV/Ri1PUy8yAAACDAAAAFQAAABgZ050kmNtYXAAAB1cAAAChQAAA/wdE0d/Y3Z0IAAAIdQAAAA0AAAANAq+BC1mcGdtAAAf5AAAAQUAAAFzBpmcN2dhc3AAAJ1wAAAADAAAAAwABwAHZ2x5ZgAAJnAAAGxKAADg/GpVnLBoZG14AAAHTAAAFhAAADPIAPyiAmhlYWQAAAGUAAAANQAAADYF/aZQaGhlYQAAAcwAAAAgAAAAJAdxBTBobXR4AAACYAAABKIAAAj0wQRTzWxvY2EAACIIAAAEZwAABHxHMIAQbWF4cAAAAewAAAAgAAAAIARXAs1uYW1lAACSvA...2hawUjGKWSTHlyN3B4j2cWs3I2964qIdNK7Bn7l3NIq2gNwdKsrkImONznSahSZTpEh+owvcW+7Mf+HMCBHCTUSS3UXS/oRb2kl/WKXkVU0IxWdKQr3VmSlVmNtdmIzdiSffjdhinO1apRR/hEi8+3rumZFRzp+eEo1XnM/Kz/ABXXNDcAeAGFUUV3wzAM/it6vowXOA1cj5nxrueojZPWynPUDv58uWO4iT+Q7pBghoLQo1A79g2VrMbK6B75jAN47FBDPU56EMfDZhxDGsfrCrqh3VC5SLURRZY7HQrWYVteKlodpgoio9vOkq8JXPbzETifDPx3LGpP54wWehazx17QCjjf5O3v49DkAG/Yfph1UIbYOhpv69k5oy1XL8G1cpkent9bGPPae7sJ96Ojb5sfFwJm1MFQTnePAla5K8HVgPDWBG5+vRbd2fwJg7xahhNv34+/Lb05R9MPTH3KQBiu2ZYkY43dmoA9tEiqcfHN+Gj2VzMA6Y+oeQ==' because it violates the following Content Security Policy directive: "default-src 'self'". Note that 'font-src' was not explicitly set, so 'default-src' is used as a fallback.

I would like a help with this, please!

FYI

ws:// needs to be allowed via CSP (Content Security Policy)

Check plug :put_secure_browser_headers present in relevant pipelines in Phoenix Router, check either default or suitable custom values are used.

Consider Content Security Policy configuration (in Phoenix) | The log of Paul Wilson

2 Likes

I updated the dependencies outdated.
Now I have the Phoenix 1.6.10.
And it wasn’t able to fix the CSP configuration.
I read the tutorial of the Paul Wilson and put this on the router.

@host :food_order
        |> Application.fetch_env!(FoodOrderWeb.Endpoint)
        |> Keyword.fetch!(:url)
        |> Keyword.fetch!(:host)

  @content_security_policy (case Mix.env() do
                              :prod ->
                                "default-src 'self';connect-src wss://#{@host};img-src 'self' blob:;"

                              _ ->
                                "default-src 'self' 'unsafe-eval' 'unsafe-inline';" <>
                                  "connect-src ws://#{@host}:*;" <>
                                  "img-src 'self' blob: data:;"

                                "font-src data:;"
                            end)

pipeline :browser do
...
  plug :put_secure_browser_headers, %{"content-security-policy" => @content_security_policy}
end

And now fixed the problems about the:

 Content Security Policy directive "default-src 'self'"

The Safari browser now is loading ok.
But continues complaining the loading of the google fonts in all browsers.

Brave Browser

Refused to load the font '<URL>' because it violates the following Content Security Policy directive: "font-src data:".
Refused to load the font 'https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fCRc4AMP6lbBP.woff2' because it violates the following Content Security Policy directive: "font-src data:".
.
.
.

Safari

[Error] Refused to load https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfBBc4AMP6lQ.woff2 because it does not appear in the font-src directive of the Content Security Policy.

Safari is the only show the error message and after the error message shows the successfully preconnected to google fonts:

Successfully preconnected to https://fonts.googleapis.com/

How can I solve this?

I am thinking to download and install the fonts on the assets folder and use the @font-face {} on the app.css.

Hi, I think the error message is pretty self-explanatory: “Refused to load (url) because it does not appear in the font-src directive of the Content Security Policy.”

FWIW I prefer to host fonts locally…

I changed now the @CSP for add the string font-src data:

@content_security_policy (case Mix.env() do
                              :prod ->
                                "default-src 'self';connect-src wss://#{@host};img-src 'self' blob:;"

                              _ ->
                                "default-src 'self' 'unsafe-eval' 'unsafe-inline';" <>
                                "connect-src ws://#{@host}:*;" <>
                                "img-src 'self' blob: data:;" <>
                                "font-src data:;"
                            end)

And on the safari browser is like it fixed.
But the Brave, Chrome complains to this:

Refused to load the stylesheet 'https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700&display=swap' because it violates the following Content Security Policy directive: "default-src 'self' 'unsafe-eval' 'unsafe-inline'". Note that 'style-src-elem' was not explicitly set, so 'default-src' is used as a fallback.

Firefox:

Content Security Policy: As configurações da página bloquearam o carregamento de um recurso em https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700&display=swap (“default-src”).

Sorry, I never experienced this problem of the CSP.
And I was just following the tutorial to fix.
And I have no idea to fix this.
thank you for reply @evadne

I will try, thanks @kokolegorille!

I saw the link but is for webpack. I am using ESBuild with the Phoenix 1.6.10.
I am trying all the day and nothing I also tried some tutorials like this:

and I have no success :rage:!

I was able to fix installing the fonts locally.
So, I copy and paste the fonts locally on the priv/static/fonts folder:

priv/static/fonts
├── aclonica-v18-latin-regular.woff2
└── lobster-v28-latin-regular.woff2

I put it there because the documentation of the phoenix recommends there like the images as well.

On the app.css I put:

@font-face {
  font-family: 'Aclonica';
  src: url("/fonts/aclonica-v18-latin-regular.woff2");
}

@font-face {
  font-family: "Lobster";
  src: url("/fonts/lobster-v28-latin-regular.woff2");
}

So, it is possible to use on the CSS like:

body {
  font-family: 'Lobster', 'Aclonica', sans-serif, cursive;
}

To use them with the Tailwind CSS config I put this on the tailwind.config.js:

// See the Tailwind configuration guide for advanced usage
// https://tailwindcss.com/docs/configuration
module.exports = {
  content: [
    './js/**/*.js',
    '../lib/*_web.ex',
    '../lib/*_web/**/*.*ex'
  ],
  theme: {
    extend: {
      fontFamily: {
        'sans': ['Helvetica', 'sans-serif'],
        'aclonica': ['Aclonica'],
        'lobster': ['Lobster']
      },
    },
  },
  plugins: [
    require('@tailwindcss/forms')
  ]
}

So now it is possible to use the fonts in the classes using like this:

  • using the Font Aclonica
class="font-aclonica"

or

  • using the Font Lobster
class="font-lobster"

And the secret for don’t have any error complaints on the console was the change of the font-src:
I changed to use this "font-src 'self' data:;" on the router.ex file.
So the final code of the router.ex file:

@host :food_order
        |> Application.fetch_env!(FoodOrderWeb.Endpoint)
        |> Keyword.fetch!(:url)
        |> Keyword.fetch!(:host)

  @content_security_policy (case Mix.env() do
                              :prod ->
                                "default-src 'self';connect-src wss://#{@host};img-src 'self' blob:;"

                              _ ->
                                "default-src 'self' 'unsafe-eval' 'unsafe-inline';" <>
                                "connect-src ws://#{@host}:*;" <>
                                "img-src 'self' blob: data:;" <>
                                "font-src 'self' data:;"
                            end)

  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_live_flash
    plug :put_root_layout, {FoodOrderWeb.LayoutView, :root}
    plug :protect_from_forgery
    plug :put_secure_browser_headers, %{"content-security-policy" => @content_security_policy}
  end

I was trying to use the import with the google fonts but I was having the errors complaining the font-src duplicate, etc… I don’t know how to fix the usage of the google fonts by URL import.
Is something about the CSP.

The print using the fonts:

1 Like

This might help you generate a good CSP policy:CSP Generator

There is also an example for Google Fonts.

External Fonts
Using the external (Google) fonts has the benefit the font is probably already cached by a visit to another website using them too. Drawback: The hoster and it’s tracking and also more permissive CSP.

Self hosting
Depending on the use case, you might create a subset of the font and serve that to users to keep the data over the wire to a minimum. No tracking, restrictive CSP, but still a fast initial render with the correct font!

And when you want to go ever further, there is this (upcoming) standard: A New Way To Reduce Font Loading Impact: CSS Font Descriptors — Smashing Magazine