Content Security Policy
What is Content Security Policy
Content Security Policy (CSP) is an HTTP response header that gets sent from the server and it tells the browser approved sources of content that the browser can load. It is an easy and effective way to prevent Cross Site Scripting (XSS) attacks. It is supported by all common browsers (Full Table).
Why Use Content Security Policy
When a browser loads a web page there are a lot of pieces that it loads, such as images, scripts, fonts, and CSS. Using my blog as an example, all the content like pictures, posts, and the majority of scripts are local. There are a couple elements that are not hosted locally, such as some scripts and the font are loaded from Disqus for comments and Google for the font. Your browser has no way of knowing what is good to load and what is bad to load, so it just loads everything whether it is from blog.jwhite.network or malicioussite.com. By adding a CSP header, you can tell the browser that loading elements from blog.jwhite.network are fine, but anything else is bad to load.
Defining a Content Security Policy
There are 14 directives and policy is made up of one or more directives.
Directives | Definitions |
---|---|
default-src | Default policy that is applied to all elements if they are not set. |
script-src | Valid sources for javascript. |
style-src | Valid sources for stylesheets. |
img-src | Valid sources for images. |
connect-src | Valid sources for ajax, WebSocket or EvenSource. |
font-src | Valid sources for fonts. |
object-src | Valid sources of plugins like <object> or <embed> . |
media-src | Valid sources of <audio> or <video> . |
sandbox | Enables sandbox for request's resources. |
report-uri | Tells the browser to make POST reports of policy failures. |
child-src | Defines valid source for web works and elements such as <frame> and <iframe> . |
form-actions | Valid sources for <form> . |
frame-ancestors | Valid sources for <frame> , <iframe> , <object> , <embed> , and <applet> . |
plugin-types | Defines valid MIME types for plugins invoked via <object> and <embed> . |
The directives and what they define, courtesy of Content-Security-Policy.com.
Each one of those directives that ends in src supports a list of values called the source list. Multiple source list values can be used apart from 'none' which is used as the only value.
Source Value | Description |
---|---|
* | Wildcard. Allows for all URLs, but not data: |
'none' | Denies resources from all sources. |
'self' | Allows resources from the same origin (has to match scheme, host, and port). |
data: | Allows resources via the data scheme |
sub.example.com | Allows resources from specified domain name |
*.example.com | Allows resources from any subdomain under example.com |
https://example.com | Allows resources to be loaded only with HTTPS matching the domain. |
https: | Allows resources to be loaded only with HTTPS on any domain. |
'unsafe-inline' | Allows use of inline elements. |
'unsafe-eval' | Allows use of unsafe dynamic code evaluations. |
'nonce-' | Allows script or style tag to execute if the nonce matches the header value. |
'sha256-' | Allows script or style to execute if it matches the hash. |
Using Content Security Policy
A simple CSP would be:
default-src 'self'; img-src *; script-src https://userscripts.example.com
This policy allows anything to be loaded from itself with the default-src set to self. It allows images to be allowed from anywhere. Javascript can only come from https://userscripts.example.com. Items like fonts and stylesheets would have to load from the host itself.
Limitations & Wrap up
CSP works on the idea of whitelisting origins, which means that using inline javascript or CSS is considered unsafe. I use Jekyll for my blog and theme that I have uses scss. What this means is that the styling is all loaded inline and you can see this if you inspect this pages and look in the <head>
tag. There is <style>
and it contains all the CSS for my blog. While not as bad as inline javascript, it is still better to avoid. It is something that I would like to fix.
Content Security Policy is a great way to defend against XSS attacks. It works by telling your browser to whitelist origins and blocking everything else. It is easy to implement a universally supported by browsers. It is definitely something to look setting up if you do not have it already.