Content Security Policy Demystified
Content Security Policy is low-hanging fruit for your website's security.
Just a single line gives us complete control over which resources can be downloaded (and possibly executed) from where. Yes, it might look a bit cryptic for an untrained eye, but it's in fact, very straightforward.
Using it wisely is a simple way to mitigate certain types of attacks like Cross Site Scripting, Form Hijacking, and the Packet Sniffing Attack.
If you have never heard about those, please take your time and make yourself familiar.
No, it's not boring.
How to use it?
There are two ways to set up a CSP policy:
- As a response header
Content-Security-Policy: YOUR_POLICY
- As a meta tag
<meta http-equiv="Content-Security-Policy" content="YOUR_POLICY">
The policy itself looks the same in both cases.
An example
Let's start by looking at a simple example.
default-src 'self' *.mywebsite.org; img-src *; script-src userscripts.example.com 'unsafe-inline'; img-src cdn.example.com;
With CSP, we define a set of rules per each resource type, and those rules are separated with a semicolon.
-
default-src 'self' *.mywebsite.org
is the policy that works by default for anything we don't mention specifically. In this case, we allow to fetch resources from the current domain (self
) plus all of the subdomains ofmywebsite.org
. -
script-src userscripts.example.com 'unsafe-inline'
When it comes to scripts, we allow them to only load from theuserscripts.example.com
domain. No others will be allowed. -
'unsafe-inline' allows for executing inline scripts (that is scripts inside
<script>...</script>
). By default, those are not allowed, and for a good reason. But sometimes, you might want to allow it. -
Finally, we allow images to only be downloaded from a CDN with
img-src cdn.example.com
.
The structure of a CSP
Now that we've seen an example, it's easy to see a pattern.
<directive> <source1> <source2> ...; <directive> <source1> <source2> ...; ...
A directive is usually some resource type.
script-src
define rules for scriptsstyle-src
for stylesfont-src
, you guessed it- and many others
The default-src
directive, as mentioned above, is a special kind of directive which defines the default rules for the resources we haven't specified directly to fall back to.
The sources are mostly places from which the particular resource can be fetched.
'self'
means the current domain excluding the subdomains*
means "from anywhere"https:
means "from anywhere as long as it's using TLS" (note the last colon - it's mandatory)- a specific domain
mydomain.com
- subdomains of a specific domain
*.mydomain.com
- and there are more.
Some of the directives can be used with special sources.
For example, the already mentioned unsafe-inline
(allowing to execute of inline code or applying inline styles) makes sense for styles and scripts, but not for fonts.
More Examples
Let's look at some practical examples.
default-src 'self'
Simple and elegant. Allow loading all the resources only from the current domain. The inline scripts and styles are not allowed.
default-src 'self'; style-src 'self' cdn.mywebsite.com; img-src 'self' cdn.mywebsite.com
Allow loading images and stylesheets from a CDN.
default-src 'self'; form-action: 'self'
Forbid any form actions other than the current domain. Note that for some reason, form-action
doesn't fallback to default-src
, so we have to set it specifically.
default-src 'self'; report-uri https://mywebsite.com/csp/report;
Finally, browsers can notify you by sending a report anytime a violation occurs.
It's handy to know if your website is working correctly for everyone or if someone's trying to hack you or your users.
Then it is your job as a developer to make sure that /csp/report
endpoint can accept and store the reports. To learn more, read here.
Further reading
I hope this article helped you understand how the CSP works and encouraged you to use it today as it is so simple and powerful.
Here are some links for you to dive deeper.