Use Content Security Policy (CSP) headers to prevent loading of untrusted resources and mitigate cross-site scripting (XSS) attacks
3 min read
By Henrik Walker Moe
December 14, 2018
CSP is a built-in browser security feature that is designed to prevent this "attack-vector" and is luckily one of the low-hanging fruits you can apply to secure your site.
Before moving ahead let's define a few key concepts in this article.
An attacker exploits a vulnerability by using a technical approach or method to access/inject/scan assets. This approach is often referred to as a vector. There might be one or more vectors for any given vulnerability, varying in difficulty to execute.
If your website uses third-party resources then those have "external origins".
CSP's directives supports
self for own origins and URLs for external origins.
Your server should return the HTTP response header:
If you want to start with just trusting your own resources, use:
Content-Security-Policy: default-src 'self'
This tells your browser "hey, just load resources from my own domain/origin.". This mitigates Cross-Site Scripting (XSS) attacks where an attacker is trying to exploit a vulnerability on your website by injecting a script into your website from e.g.
When a browser attempts to load a resource but is blocked by the CSP-rules, it can report the CSP-violation by posting to a URL using the
Content-Security-Policy: report-uri '/some-url'
This lets you identify if someone's attempting something malicious or if you just forgot to whitelist one of your resources. Either way it's a useful tool to monitor your CSP-rules in production.
You need to implement a back-end to consume the report or use an external service, e.g. report-uri as a service.
nonce (number used once) can be used to make exemptions to your CSP-rules. By generating a unique one-time use value on the server-side and providing it to the front-end, you can trust that the content you are allowing to pass-through your CSP-rules is yours and trusted.
Content-Security-Policy: script-src 'unsafe-inline';
A better way of making exemptions is to provide a value to the
nonce attribute on the
<script>block as the
<script nonce="2726c7f26c">var inline = 1;</script>
Content-Security-Policy: script-src 'nonce-2726c7f26c';
As long as the two
Remember to re-generate the value per page-load and keep the
nonce value random.