Content Security Policy (or CSP) is very complex and powerful security-related HTTP header, that might be complex to implement, but essential in limiting what browser is allowed to load when browsing your website.

This article continues from the previous two articles on the subject of HTTP Headers related to security: Security related HTTP Headers, Part 1: Introduction and Security related HTTP Headers, Part 2: Referrer Policy.

How browser loads website pages?

When you visit any website, any website page, browser loads main page content (HTML usually), and then it processes that page and continues loading various resources: CSS files, JavaScript files, images… or running scripts that are inside the HTML. But, the browser has no idea what resources are safe to load or run, and will load all found and run everything. This opens the website and the website visitor to potential attack by the malicious script embedded on the page (unvalidated comment with a malicious script or other methods).

What CSP does?

Content Security Policy purpose is to tell the browser what resources are safe to load, and what resources should be ignored. Same goes for inline scripts or other elements executed by the browser. But, configuring CSP can be a very challenging job, and considering how many elements the CSP can have, it is prone to mistakes. Because of that, CSP can work in reporting-only mode, and it also features a way for browsers to send reports of violations back to your website for processing. While in reporting-only mode, the browser will load everything as usual, but in the browser console, you will see all the CSP related warnings.

The scope of this article can’t cover every type of content or content allowed value, sandbox or reporting format. CSP is very complex header and requires experience, testing, change and error approach to the setup. This article is introduction to the CSP header, and possibilities it offers when it comes to the security.

Elements for CSP

CSP includes a wide range of elements that can be used to define allowed resources for scripts, styles, images, frames, fonts and more. For each element, you can use multiple values. Here is the list of the content based elements:

  • default-src: this is the fallback rule that will be used for any element that is not defined in the CSP rule.
  • script-src: rules related to JavaScript file
  • style-src: rules related to the CSS files
  • img-src: rules related to images
  • connect-src: rules related to AJAX or WebSocket technologies
  • font-src: rules related to web fonts
  • object-src: rules related to embedded objects (OBJECT, APPLET, EMBED)
  • media-src: rules related to embedded audio and video files (AUDIO, VIDEO)
  • child-src: rules related to embedded external pages (IFRAME)
  • form-action: rules for allowed actions in the page forms
  • frame-ancestors: rules defining the websites allowed to use IFRAME

And, there are few more elements that can be included:

  • sandbox: define how the page will be run, allowing only some of the resources to be accepted
  • plugin-types: list of browser plugins allowed to run
  • reflected-xss: equivalent to the X-XSS-Protection HTTP header
  • report-uri: URL to the page where CSP reports will be sent, you need to implement processing of these reports if you want to save them.

For content-based elements, there are many allowed values:

  • *: all URL’s allowed
  • ‘none’: all the resources for the type are restricted
  • ‘self’: all resources for own domain are allowed
  • data:: resources specified as ‘data’ are allowed (images with base64 encoded values)
  • https:: resources for any domain, only allowed from HTTPS
  • sub.domain.com: URL’s belonging to subdomain of the domain allowed
  • *.domain.com: URL’s belonging to any subdomain of the domain allowed
  • https://domain.com: URL’s belonging to domain, on HTTPS only
  • ‘unsafe-inline’: allow inline elements (scripts, styles, onclick and other attributes)
  • ‘unsafe-eval’: allow dynamic code evaluation via eval() function
  • ‘nonce-‘: allow scripts and styles with the matching nonce attribute
  • ‘sha-256’: allow scripts and styles matching hashed content

Some rules examples

To get some feel for the way CSP works, here is a basic rule that will allow resources from your own website only, and only from HTTP:

Content-Security-Policy: “default-src ‘self’ https:;”

And, here is the policy allowing only some types of resources, and only via HTTPS, and this will also stop IFRAMES or objects:

Content-Security-Policy: “default-src ‘none’; script-src ‘self’ https:; connect-src ‘self’ https:; img-src ‘self’ https:; font-src ‘self’ https:; media-src ‘self’ https:; style-src ‘self’ https:;”

Here is something a bit more complex, to allow Google Analytics and social network share buttons:

Content-Security-Policy: script-src ‘self’ ‘unsafe-inline’ www.google-analytics.com ajax.googleapis.com platform.twitter.com https; child-src ‘self’ plusone.google.com facebook.com platform.twitter.com https:;”

Check out the websites listed at the bottom, for more information and examples.

Do not use these examples on your website! They are examples, only, they will be incomplete for most uses and you need to adjust CSP rules to your website, and always in the Report Only mode only, until you do all the tests needed and everything works as expected.

WordPress limitations

There are some real limitations when it comes to configuring CSP in WordPress (and most likely with any other CMS). If you use script and style rules, you must allow for ‘unsafe-inline’ value, or a lot of the WordPress added code and code added by plugins or themes will stop working. Many JavaScript scripts are added directly into HTML, and at the moment there is no easy way to set nonce attributes for each one for use with the CSP. What’s more, nonce has to be generated with each page load, and that will make caching impossible.

WordPress doesn’t have a centralized way for adding embedded scripts and styles, so the CSP nonce support is very complex to implement. Right now, it would require parsing HTML of the page, generating the nonce, and modifying tags using regular expressions. Even if that is done, caching would be a problem again, so it is better not to bother with this until there is a better way to do it.

Using CSP, yes or no?

If you have enough experience and patience to configure the CSP, it is definitely a must use HTTP header. Dev4Press website uses CSP for a while now, with the implemented reporting capabilities (via our GD Security Toolbox Pro plugin), and we have logged over 10.000 abuse reports from attempts to abuse CSP. We have noticed that a lot of users have malicious scripts and extensions in their browser attempting to inject code into the pages they browse. It is also disturbing how many things legitimate applications inject into browsed pages. Skype, for instance, tries to inject scripts, styles and even fonts into every page user visits.

More on CSP

This was only the introduction to Content Security Policy HTTP Header. To learn more on how to create rules, test those rules, set up reporting and more, check out these websites:

Please wait...

SiteGround

Great managed hosting experience, fast and secure with amazing support.
Siteground Hosting

PHP 7.0 and 7.1, free Let's Encrypt SSL certificates, cache and optimizations for WordPress. Choose between great shared WordPress hosting plans (starting from 3.95 €/month), high performance cloud hosting (starting from 64.00 €/month)...

Disclosure: This post contains affiliate links, which means that I receive compensation if you make a purchase using this link.

About the author

MillaN
MillaN
Dev4Press owner and lead developer

Programmer since the age of 12 and now WordPress developer with more than 8 years of WordPress experience, author of more than 100 plugins and more than 20 themes.

Learn More

GD Security Toolbox Pro
A collection of many security related tools for .htaccess hardening with security events log, ReCaptcha, firewall, and tweaks collection, login and registration control and more.
GD Security Toolbox Pro Logo

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *