DEV Community

loading...
Cover image for Frontend Security: Content Security Policy

Frontend Security: Content Security Policy

madsstoumann profile image Mads Stoumann ・3 min read

In my previous article on security, I wrote about npm audit and script integrity. Next up is Content Security Policy, or CSP for short.

This can either be added as response-headers on the server, or as a <meta>-tag in the html.

I'm going to focus on the latter here.

A CSP will tell the webpage from which domains it will allow loading images, fonts, iframes, scripts etc. from:

<meta http-equiv="Content-Security-Policy" content="
  default-src;
  script-src 'self';
  style-src 'self';
  img-src 'self' data:;
  font-src;
  connect-src 'self';
  media-src 'self';
  object-src 'none';
  child-src;
  frame-src;
  form-action;
  base-uri;
  manifest-src 'self';
">
Enter fullscreen mode Exit fullscreen mode

It's one long string within the double quotes, so I've added line-breaks and tabs for clarity.

Each entry ends with a semicolon ;

Note the word 'self'. That's how you allow to run the various types from the same domain as the current document.

Scripts

To allow a script from an external site, maybe a delivery network such as unpkg.com, add unpkg.com to the script-src-part of the CSP:

script-src 'self' unpkg.com;
Enter fullscreen mode Exit fullscreen mode

Cloudflare provides edge-caching and/or minification for assets, as well as a "Rocket Loader™", which will improve the paint-time for sites using JavsScript. I use it on my sites, but had to add this to my CSP:

script-src 'self' ajax.cloudflare.com;
Enter fullscreen mode Exit fullscreen mode

A new entry is just a space, so combined, the current script-src looks like this:

script-src 'self' unpkg.com ajax.cloudflare.com;
Enter fullscreen mode Exit fullscreen mode

Google Fonts

For Google Fonts, you'll have to add entries to both font-src and style-src:

font-src fonts.gstatic.com;
style-src 'self' fonts.googleapis.com ;
Enter fullscreen mode Exit fullscreen mode

YouTube

For YouTube, you need entries to frame-src since it's iframe-based and to img-src as it provides thumbnail images as well. CSP is not always easy, but it's the quickest way to add an extra layer of protection to your site!

frame-src *.youtube.com;
img-src 'self' img.youtube.com data:;
Enter fullscreen mode Exit fullscreen mode

If you include the YouTube API as well, you must add it to the script-src:

script-src *.youtube.com;
Enter fullscreen mode Exit fullscreen mode

YouTube-videos works with these additions, but will occasionally generate errors for it's "doubleclick"-network and others. You can just ignore these, or add them to your CSP (if you trust them!):

script-src: https://www.googleadservices.com https://googleads.g.doubleclick.net https://www.google.com
img-src: https://www.google.com
frame-src: https://bid.g.doubleclick.net
Enter fullscreen mode Exit fullscreen mode

Vimeo

Vimeo just need the frame-src:

frame-src: *.vimeo.com
Enter fullscreen mode Exit fullscreen mode

But if you want to use their API, add an entry to script-src as well:

script-src: *.vimeo.com
Enter fullscreen mode Exit fullscreen mode

Warning: Marketeers and SEO-people hate CSP's!

With a CSP in place, marketeers can no longer just add a cool new tracking-script via Google Tag Manager or similar. So: be prepared to hear a lot of complaints, unless you create a CMS-block, where they can add/remove CSP entries themselves!

Google Chrome supports many more CSP-entries than listed above. Unfortunately most of these doesn't work in Apple Safari, and can actually cause it to not parse JavaScript, so be sure to test in all browsers.

More info here:

https://content-security-policy.com/

And to help you create one:

https://report-uri.com/home/generate

Bonus: Add preconnect

While you're adding entries to your CSP, add a <link rel="preconnect">-tag for the same entries to speed up communication between your site and these resources.

Example for "Google Fonts":

<link rel="preconnect" href="https://fonts.gstatic.com">
Enter fullscreen mode Exit fullscreen mode

Thanks for reading!

Discussion (9)

pic
Editor guide
Collapse
jankapunkt profile image
Jan Küster

With a CSP in place, marketeers can no longer just add a cool new tracking-script via Google Tag Manager or similar. So: be prepared to hear a lot of complaints, unless you create a CMS-block, where they can add/remove CSP entries themselves!

No offence, but no marketeer or sales person will ever get my permission or an implementation to change any part of the CSP on their own.

Collapse
madsstoumann profile image
Mads Stoumann Author

I've worked for clients who removed a CSP-implementation or chose not to have a CSP, because marketeers wanted the freedom to implement any script via Google Tag Manager. In these cases, a CMS-block is much better than not having a CSP, although it's dangerous territory, and I agree with you.

Collapse
jankapunkt profile image
Jan Küster

Why am I not surprised that some clients literally come up with such decisions :-/
But under these circumstances I totally agree - better having them edit (a part of) the CSP than having none. I wonder if this would be implemented in a workflow, where the system (using include/exclude lists) or a human can review these edits, before actually publishing them.

Thread Thread
madsstoumann profile image
Mads Stoumann Author

Yes, any changes to the "CSP-config-block" can be previewed and verified before published.

Collapse
shaialon profile image
Shai Alon

Great article!

Hope it's ok, but would also like to recommend:
cspscanner.com/ - CSP scanner and evaluator

csp-evaluator.withgoogle.com/ - CSP evaluator by Google

rapidsec.com/ - Free report-uri & CSP generator.

Collapse
madsstoumann profile image
Mads Stoumann Author

More than OK - thanks!

Collapse
ronaldohoch profile image
Ronaldo Hoch

Nice!
I'm writing some content about too, but i never finished :D

Collapse
amarbalu profile image
Amar Balu

Hi Mads, It’s been a wonderful article.
My CSP headers url gets blocked, even it is mapped inside meta tag. Can you help me out with that!!! I don’t know where I messed the things.

Collapse
madsstoumann profile image
Mads Stoumann Author

Hi Amar, all CSP-errors are listed in the Console of Dev Tools. Here you’ll be able to see exactly what’s wrong.