69

I'm trying to use Google Fonts and I've never had any problems, but now when I try to add the CSS file on my header I get this error on the console:

Refused to load the stylesheet 'http://fonts.googleapis.com/css?family=Whatever' because it violates the following Content Security Policy directive: "style-src 'self' 'unsafe-inline'".

José María
  • 2,835
  • 5
  • 27
  • 42
  • So you have to change the CSP header you send to allow that resource. If you look at the current setting you can clearly see that styles are limited to the location `self` which most likely does not include `googleapis.com` . – arkascha Nov 29 '15 at 16:16
  • I've tried modifying it using a meta tag and adding some things I've seen on the internet but I have not been able to solve the this... – José María Nov 29 '15 at 16:17
  • 2
    This has nothing to do with meta tags. A `CSP header` is an http header, so part of the protocol, not the content. You send it, be it by purpose or accidentally. Maybe because you use some framework, but we cannot say any more without you posting more details. – arkascha Nov 29 '15 at 16:17
  • Hmmmm, I'm using Meteor JS – José María Nov 29 '15 at 16:20
  • 3
    You can easily check that header yourself if you don't believe the error message you see: just open your browsers development console and look at the headers of the basic requests done. They will contain said header. Or you use a network sniffer, comes out the same. – arkascha Nov 29 '15 at 16:22

6 Answers6

104

There are two things to fix here:

  • Use https for the Google fonts link (https://fonts.googleapis.com/css?family=Whatever)
  • Authorize https://fonts.googleapis.com in style-src directive and https://fonts.gstatic.com in font-src directive: "style-src 'self' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com"
Yves M.
  • 29,855
  • 23
  • 108
  • 144
Rolinh
  • 1,269
  • 1
  • 11
  • 8
  • 5
    what is the `data:` for? – Daniel Birowsky Popeski Sep 02 '16 at 08:55
  • 2
    `Allows data: URIs to be used as a content source.` From https://developer.mozilla.org/en/docs/Web/Security/CSP/CSP_policy_directives#Data – James Spencer Oct 26 '16 at 10:42
  • 34
    For others looking at this answer, don't copy over the 'unsafe-inline' as it lowers security for no good reason - it's not needed for the fonts to work. The only reason why it's there is because the OP had it in his original code. Use `style-src 'self' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com;` – Kevin Lee Jul 16 '17 at 14:12
  • 3
    @KevinLee If you turn your comment into an answer, I'd upvote it. – lilalinux Aug 04 '18 at 10:10
  • 1
    @KevinLee actually it might very well be needed if you inline your styles - witch is very common in react applications for instance. – jBoive Nov 27 '18 at 08:24
66

If you're like me and a little confused because every answer is just saying you need to authorize a URL in a style-src directive without showing how to do it, here's the full tag:

<meta http-equiv="Content-Security-Policy" content="style-src 'self' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com;">
Yves M.
  • 29,855
  • 23
  • 108
  • 144
Owen
  • 4,229
  • 5
  • 42
  • 50
  • 1
    Do the content options you left out like default-src etc lower security, or is it the same as not having a `meta csp` tag in the first place? – Drenai Mar 19 '18 at 14:44
  • 1
    With the `unsafe-inline` attribute allowed, it actually lowers security. The tag can work fine without that, as it makes your app more vulnerable to XSS attacks. – Paul Razvan Berg Mar 30 '18 at 09:11
  • 1
    removed the 'unsafe-inline' – Owen Apr 09 '18 at 14:38
  • I just used it as follows: `` – Yvonne Aburrow Apr 09 '18 at 14:41
  • 1
    @Owen It's really difficult to find good info on `meta` tag csp's. I am not confident in resolving my font warning at the risk of making everything else less secure:-) My site is a portfolio site, and I don't want to be asked "why you do that??" in an interview:-) – Drenai Apr 18 '18 at 14:37
  • I was working a whole day on it and found that font-source not working on google fonts but kept that there anyway, I was using for ; style-src 'self' fonts.googleapis.com unsafe-inline' 'unsafe-eval' and it worked perfectly well – Aleksandrs Krasnovskis Sep 30 '20 at 14:41
  • If you are here wondering why this does not work for you, check also HTTP response headers for the HTML file. The response header is set by web server and if it contains stronger condition, it will overrule the `meta` tag. – Radek Matěj Mar 05 '21 at 14:26
14

There are multiple sources that can be given for Content-Security-Policy.

Below has clear details, which worked for me.

Depending on which content (css, img, font, media) source error you have, you can change the URL in the below.

<html>

<head>

  <meta http-equiv="Content-Security-Policy"
    content="
      default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; 
      style-src   'self' https://fonts.googleapis.com;
      font-src    'self' data: https://fonts.gstatic.com;
      img-src     'self' data: content:;
      media-src   *;
            "
  />

 <title>My page title</title>

</head>

<body>
  some text
</body>

</html>

Hope that helps.

Manohar Reddy Poreddy
  • 25,399
  • 9
  • 157
  • 140
6

When working with Helmet, the following works perfectly (written in TypeScript):

import * as express from 'express';
import { Express } from 'express';
const helmet = require('helmet');
const expressApp: Express = express(); // Create Express instance.

expressApp.use(
  helmet.contentSecurityPolicy({
    directives: {
      fontSrc: [
        "'self'", // Default policy for specifiying valid sources for fonts loaded using "@font-face": allow all content coming from origin (without subdomains).
        'https://fonts.gstatic.com' // Google Fonts.
      ],
      styleSrc: [
        "'self'", // Default policy for valid sources for stylesheets: allow all content coming from origin (without subdomains).
        'https://fonts.googleapis.com' // Google Fonts.
      ],
    }
  })
);
Daniel Danielecki
  • 8,508
  • 6
  • 68
  • 94
2

The combinations above did not work for me. My code is importing the fonts from an .scss file like this:

@import url('https://fonts.googleapis.com/icon?family=Material+Icons');

I added the following:

  • default-src was set to just 'self'. This is not necessary, but I wanted everything else locked down. This restriction may trigger errors in the browser console. Adapt as needed. I had to add wss: scheme, to allow a web socket connection for the Angular debugger.
  • style-src needed the 'unsafe-inline' keyword. I suspect that it is because the style is packed/minimized.
  • script-src was also needed with the 'unsafe-inline' keyword. Although I checked the stylesheet downloaded and did not see anything obvious, I think that there must be something there that is considered a script.
  • font-src needed the data: scheme. The browser console was giving an error fetching data:application/font-woff;charset=utf-8… (“font-src”). This may be something coming from a different place in my Angular code, but it may be useful for someone.

Below the final thing.

default-src 'self' wss:;
style-src 'self' https://fonts.googleapis.com 'unsafe-inline';
script-src 'self' https://fonts.googleapis.com 'unsafe-inline';
font-src 'self' data: https://fonts.gstatic.com
JPortillo
  • 543
  • 3
  • 9
1

Hi if you are adding in server.js then it should be like this

let  securityPolicy = `default-src 'self' 'unsafe-eval' 'unsafe-inline'; ` +
`script-src 'self' 'unsafe-inline' 'unsafe-eval' ` +
`img-src 'self' data:  ` +
`style-src 'self' 'unsafe-inline' 'unsafe-eval'  ` +
`font-src https://fonts.googleapis.com 'self' data:  ` 


res.header('Content-Security-Policy', res.header('Content-Security-Policy', securityPolicy))