A Content Security Policy (CSP) is a great way to reduce or completely remove Cross Site Scripting (XSS) vulnerabilities. With one, you can effectively disallow inline and external scripts from untrusted sources. You define the policy via an HTTP header with rules for all types of assets.
Content-Security-Policy: default-src 'self'; script-src 'self' https://www.google-analytics.com;
The example above allows assets (JS, CSS, images, etc.) from the default source — the same origin ('self'
). Scripts are also allowed from Google Analytics to make the tracking code work. Everything else is disallowed.
What is a Content Security Policy (CSP)?
Content Security Policy (CSP) is a policy to mitigate against cross-site scripting issues, and we all know that cross-site scripting is bad.
There’s work involved; you’ll need to learn how to do fundamental tasks differently…
I’m not going to try and convince you that CSP is a warm-and-fuzzy new policy. There’s work involved; you’ll need to learn how to do fundamental tasks differently, but will boost site security exponentially.
There are plug-and-play solutions for some of the popular CMS out there like Drupal and WordPress that’ll help speed up the process a little.
Mitigating cross site scripting
A primary goal of CSP is to mitigate and report XSS attacks. XSS attacks exploit the browser’s trust of the content received from the server. Malicious scripts are executed by the victim’s browser because the browser trusts the source of the content, even when it’s not coming from where it seems to be coming from.
CSP makes it possible for server administrators to reduce or eliminate the vectors by which XSS can occur by specifying the domains that the browser should consider to be valid sources of executable scripts. A CSP compatible browser will then only execute scripts loaded in source files received from those whitelisted domains, ignoring all other script (including inline scripts and event-handling HTML attributes).
As an ultimate form of protection, sites that want to never allow scripts to be executed can opt to globally disallow script execution.
Mitigating packet sniffing attacks
In addition to restricting the domains from which content can be loaded, the server can specify which protocols are allowed to be used; for example (and ideally, from a security standpoint), a server can specify that all content must be loaded using HTTPS.
A complete data transmission security strategy includes not only enforcing HTTPS for data transfer, but also marking all cookies with the secure flag and providing automatic redirects from HTTP pages to their HTTPS counterparts.
Sites may also use the Strict-Transport-Security
HTTP header to ensure that browsers connect to them only over an encrypted channel.
Implementing a Content Security Policy (CSP)
Configuring Content Security Policy involves adding the Content-Security-Policy
HTTP header to a web page and giving it values to control resources the user agent is allowed to load for that page.
For example, a page that uploads and displays images could allow images from anywhere, but restrict a form action to a specific endpoint. A properly designed Content Security Policy helps protect a page against a cross site scripting attack.
Specifying your policy
You can use the Content-Security-Policy
HTTP header to define your policy, where ‘policy’ is the directive:
Content-Security-Policy: policy
The policy is a string containing the policy directives describing your Content Security Policy.
Writing a policy
CSPs are made up of one or more directives, multiple directives are separated with a semi-colin ;
. Your policy should include a default-src
policy directive, which is a fallback for any resource type that you don’t explicitly establish (for a complete list, see the description of the default-src
directive).
A policy needs to include a default-src
or script-src
directive to prevent inline scripts from running, as well as blocking the use of eval()
. In addition, it also needs to include a default-src
or style-src
directive to restrict inline styles from being applied from a style
element or a style
attribute. restrict inline styles from being applied from a style
element or a style attribute.
Content Security Policy Browser Support
CSP is designed to be fully backward compatible; browsers that don’t support it sill work with servers that implement it, and vice-versa. If one is implemented and the browser doesn’t support it, it will simply ignore it. Instead, it will default to the standard same-origin policy for web content.
Header | Chrome | Firefox | Safari | Internet Explorer |
---|---|---|---|---|
Content-Security-Policy (CSP 1.0) | 25+ | 23+ | – | – |
X-Content-Security-Policy | - | 4.0+ | - | 10+ Limited |
X-Webkit-CSP | 14+ | - | 6+ | - |
X-Content-Security-Policy
HTTP header was used. Firefox 23 and later use the now-standard Content-Security-Policy
header. During the transition from the previous header to the new header, sites can send both the X-Content-Security-Policy
and Content-Security-Policy
headers. In this situation, the X-Content-Security-Policy
will be ignored and the policy contained in the Content-Security-Policy
header will be used.For more browsers and version support, take a look at caniuse.com/contentsecuritypolicy.
Content Security Policy Examples
Here's some common scenarios that arise when writing your security policy:
A web site administrator wants all content to come from the site's own domain, excluding even subdomains.
Content-Security-Policy: default-src 'self'
A web site administrator wants to allow content from a trusted domain and all its subdomains.
Content-Security-Policy: default-src 'self' *.mydomain.com
A web site administrator wants to allow users of a web application to include images from any domain in their custom content, but to restrict audio or video media to come only from trusted providers, and all scripts only to a specific server that hosts trusted code.
Content-Security-Policy: default-src 'self'; img-src *; media-src media1.com media2.com; script-src userscripts.example.com
Here, by default, content is only permitted from the document's original host, with the following exceptions:
- Images may loaded from anywhere (note the "*" wildcard).
- Media is only allowed from media1.com and media2.com (and not from subdomains of those sites).
- Executable script is only allowed from userscripts.example.com.
An administrator for an online banking site wants to ensure that all its content is loaded using SSL, in order to prevent attackers from eavesdropping on requests.
Content-Security-Policy: default-src https://onlinebanking.jumbobank.com
An administrator of a web mail site wants to allow HTML in email, as well as images loaded from anywhere, but not JavaScript or other potentially dangerous content.
Content-Security-Policy: default-src 'self' *.mailsite.com; img-src *
Note that this example doesn't specify a script-src
; with the example CSP, this site uses the setting specified by the default-src
directive, which means that scripts can be loaded only from the originating server.
Testing Your Policy
To ease deployment, CSP can be deployed in "report-only" mode. The policy is not enforced, but any violations are reported to a provided URI. Additionally, a report-only header can be used to test a future revision to a policy without actually deploying it.
You can use the Content-Security-Policy-Report-Only
HTTP header to specify your policy, like this:
Content-Security-Policy-Report-Only: policy
If both a Content-Security-Policy-Report-Only
header and a Content-Security-Policy
header are present in the same response, both policies are honored. The policy specified in Content-Security-Policy
headers is enforced while the Content-Security-Policy-Report-Only
policy generates reports but is not enforced.
X-Content-Security-Policy-Report-Only
header was used before Firefox 23. If both the X-Content-Security-Policy-Report-Only
and Content-Security-Policy-Report-Only
are sent, the Content-Security-Policy-Report-Only
will be used and the X-Content-Security-Policy-Report-Only
will be ignored.The UserCSP Addon also helps test and develop Content Security Policies for a site.
CSP Directive Reference
Directive | Description |
---|---|
default-src | The default-src is the default policy for loading content such as JavaScript, Images, CSS, Font's, AJAX requests, Frames, HTML5 Media See the Source List Reference for possible values. |
script-src | Defines valid sources of JavaScript. |
style-src | Defines valid sources of stylesheets. |
img-src | Defines valid sources of images. |
connect-src | Applies to XMLHttpRequest (AJAX), WebSocket or EventSource . If not allowed the browser emulates a 400 HTTP status code. |
font-src | Defines valid sources of fonts. |
object-src | Defines valid sources of plugins, eg object , embed or applet . |
media-src | Defines valid sources of audio and video, eg HTML5 audio , video elements. |
frame-src | Defines valid sources for loading frames. |
sandbox | Enables a sandbox for the requested resource similar to the iframe sandbox attribute. The sandbox applies a same origin policy, prevents popups, plugins and script execution is blocked. You can keep the sandbox value empty to keep all restrictions in place, or add values: allow-forms allow-same-origin allow-scripts , and allow-top-navigation . |
report-uri | Instructs the browser to POST a reports of policy failures to this URI. You can also append -Report-Only to the HTTP header name to instruct the browser to only send reports (does not block anything). |
CSP Source List Reference
All of the directives that end with -src
support similar values known as a source list. Multiple source list values can be space seperated with the exception of *
and none
which should be the only value.
Source Value | Description |
---|---|
* | Wildcard, allows anything. |
'none' | Prevents loading resources from any source. |
'self' | Allows loading resources from the same origin (same scheme, host and port). |
data | Allows loading resources via the data scheme (eg Base64 encoded images). |
domain.example.com | Allows loading resources from the specified domain name. |
*.example.com | Allows loading resources from the any subdomain under example.com . |
https://img.example.com | Allows loading resources only over HTTPS matching the given domain. |
https: | Allows loading resources only over HTTPS on any domain. |
'unsafe-inline' | Allows use of inline source elements such as style attribute, onclick, or script tag bodies (depends on the context of the source it is applied to) |
'unsafe-eval' | Allows unsafe dynamic code evaluation such as JavaScript eval() |
All comments posted on 'Boost Site Security & Mitigate Attacks with a Content Security Policy (CSP)' are held for moderation and only published when on topic and not rude. Get a gold star if you actually read & follow these rules.
You may write comments in Markdown. This is the best way to post any code, inline like `<div>this</div>` or multiline blocks within triple backtick fences (```) with double new lines before and after.
Want to tell me something privately, like pointing out a typo or stuff like that? Contact Me.