Content Security Policy (CSP) is an added layer of security that helps to detect and mitigate certain types of attacks, including Cross Site Scripting (XSS) and data injection attacks. These attacks are used for everything from data theft to site defacement to distribution of malware.
CSP is designed to be fully backward compatible (except CSP version 2 where there are some explicitly-mentioned inconsistencies in backward compatibility; more details here section 1.1). Browsers that don't support it still work with servers that implement it, and vice-versa: browsers that don't support CSP simply ignore it, functioning as usual, defaulting to the standard same-origin policy for web content. If the site doesn't offer the CSP header, browsers likewise use the standard same-origin policy.
To enable CSP, you need to configure your web server to return the Content-Security-Policy HTTP header (sometimes you will see mentions of the X-Content-Security-Policy header, but that's an older version and you don't need to specify it anymore).
Alternatively, the <meta> element can be used to configure a policy, for example: <meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">
Threats
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.
Using 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. This article explains how to construct such headers properly, and provides examples.
Specifying your policy
You can use the Content-Security-Policy HTTP header to specify your policy, like this:
Content-Security-Policy: policy
The policy is a string containing the policy directives describing your Content Security Policy.
Writing a policy
A policy is described using a series of policy directives, each of which describes the policy for a certain resource type or policy area. Your policy should include a default-src policy directive, which is a fallback for other resource types when they don't have policies of their own (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(). A policy 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.
Examples: Common use cases
This section provides examples of some common security policy scenarios.
Example 1
A web site administrator wants all content to come from the site's own origin (this excludes subdomains.)
Content-Security-Policy: default-src 'self'
Example 2
A web site administrator wants to allow content from a trusted domain and all its subdomains (it doesn't have to be the same domain that the CSP is set on.)
Content-Security-Policy: default-src 'self' *.trusted.com
Example 3
A web site administrator wants to allow users of a web application to include images from any origin in their own content, but to restrict audio or video media to 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 origin, with the following exceptions:
- Images may load 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.
Example 4
A web site 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
The server only permits access to documents being loaded specifically over HTTPS through the single origin onlinebanking.jumbobank.com.
Example 5
A web site 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.
Enabling reporting
By default, violation reports aren't sent. To enable violation reporting, you need to specify the report-uri policy directive, providing at least one URI to which to deliver the reports:
Content-Security-Policy: default-src 'self'; report-uri http://reportcollector.example.com/collector.cgi
Then you need to set up your server to receive the reports; it can store or process them in whatever manner you feel is appropriate.
Violation report syntax
The report JSON object contains the following data:
blocked-uri- The URI of the resource that was blocked from loading by the Content Security Policy. If the blocked URI is from a different origin than the document-uri, then the blocked URI is truncated to contain just the scheme, host, and port.
disposition- Either
"enforce"or"reporting"depending on whether theContent-Security-Policy-Report-Onlyheader or theContent-Security-Policyheader is used. document-uri- The URI of the document in which the violation occurred.
effective-directive- The directive whose enforcement caused the violation.
original-policy- The original policy as specified by the
Content-Security-PolicyHTTP header. referrer- The referrer of the document in which the violation occurred.
script-sample- The first 40 characters of the inline script, event handler, or style that caused the violation.
status-code- The HTTP status code of the resource on which the global object was instantiated.
violated-directive- The name of the policy section that was violated.
Sample violation report
http://example.com/signup.html. It uses the following policy, disallowing everything but stylesheets from cdn.example.com.Content-Security-Policy: default-src 'none'; style-src cdn.example.com; report-uri /_/csp-reports
signup.html looks like this:<!DOCTYPE html>
<html>
<head>
<title>Sign Up</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
... Content ...
</body>
</html>
cdn.example.com, yet the website tries to load one from its own origin (http://example.com). A browser capable of enforcing CSP will send the following violation report as a POST request to http://example.com/_/csp-reports, when the document is visited:{
"csp-report": {
"document-uri": "http://example.com/signup.html",
"referrer": "",
"blocked-uri": "http://example.com/css/style.css",
"violated-directive": "style-src cdn.example.com",
"original-policy": "default-src 'none'; style-src cdn.example.com; report-uri /_/csp-reports"
}
}
As you can see, the report includes the full path to the violating resource in blocked-uri. This is not always the case. For example, when the signup.html would attempt to load CSS from http://anothercdn.example.com/stylesheet.css, the browser would not include the full path but only the origin (http://anothercdn.example.com). The CSP specification gives an explanation of this odd behaviour. In summary, this is done to prevent leaking sensitive information about cross-origin resources.
Browser compatibility
The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out https://github.com/mdn/browser-compat-data and send us a pull request.
| Desktop | Mobile | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Content-Security-Policy | Chrome
Full support
25
| Edge Full support 14 | Firefox
Full support
23
| IE
Full support
10
| Opera Full support 15 | Safari
Full support
7
| WebView Android Full support Yes | Chrome Android Full support Yes | Edge Mobile Full support Yes | Firefox Android Full support 23 | Opera Android ? | Safari iOS
Full support
7.1
| Samsung Internet Android Full support Yes |
base-uri | Chrome Full support 40 | Edge No support No | Firefox Full support 35 | IE No support No | Opera Full support 27 | Safari Full support 10 | WebView Android Full support Yes | Chrome Android Full support Yes | Edge Mobile No support No | Firefox Android Full support 35 | Opera Android ? | Safari iOS Full support 9.3 | Samsung Internet Android Full support Yes |
block-all-mixed-content | Chrome Full support Yes | Edge ? | Firefox Full support 48 | IE No support No | Opera Full support Yes | Safari ? | WebView Android Full support Yes | Chrome Android Full support Yes | Edge Mobile ? | Firefox Android Full support 48 | Opera Android ? | Safari iOS ? | Samsung Internet Android Full support Yes |
child-src | Chrome Full support 40 | Edge Full support 15 | Firefox Full support 45 | IE No support No | Opera Full support 27 | Safari Full support 10 | WebView Android Full support Yes | Chrome Android Full support Yes | Edge Mobile No support No | Firefox Android Full support 45 | Opera Android ? | Safari iOS Full support 9.3 | Samsung Internet Android Full support Yes |
connect-src | Chrome Full support 25 | Edge Full support 14 | Firefox
Full support
23
| IE No support No | Opera Full support 15 | Safari Full support 7 | WebView Android Full support Yes | Chrome Android Full support Yes | Edge Mobile ? | Firefox Android Full support 23 | Opera Android ? | Safari iOS Full support 7.1 | Samsung Internet Android Full support Yes |
default-src | Chrome Full support 25 | Edge Full support 14 | Firefox Full support 23 | IE No support No | Opera Full support 15 | Safari Full support 7 | WebView Android Full support Yes | Chrome Android Full support Yes | Edge Mobile ? | Firefox Android Full support 23 | Opera Android ? | Safari iOS Full support 7.1 | Samsung Internet Android Full support Yes |
disown-opener | Chrome No support No | Edge No support No | Firefox No support No | IE No support No | Opera No support No | Safari No support No | WebView Android No support No | Chrome Android No support No | Edge Mobile No support No | Firefox Android No support No | Opera Android No support No | Safari iOS No support No | Samsung Internet Android No support No |
font-src | Chrome Full support 25 | Edge Full support 14 | Firefox Full support 23 | IE No support No | Opera Full support 15 | Safari Full support 7 | WebView Android Full support Yes | Chrome Android Full support Yes | Edge Mobile ? | Firefox Android Full support 23 | Opera Android ? | Safari iOS Full support 7.1 | Samsung Internet Android Full support Yes |
form-action | Chrome Full support 40 | Edge Full support 15 | Firefox Full support 36 | IE No support No | Opera Full support 27 | Safari Full support 10 | WebView Android Full support Yes | Chrome Android Full support Yes | Edge Mobile No support No | Firefox Android Full support 36 | Opera Android ? | Safari iOS Full support 9.3 | Samsung Internet Android Full support Yes |
frame-ancestors | Chrome Full support 40 | Edge Full support 15 | Firefox
Full support
33
| IE No support No | Opera Full support 26 | Safari Full support 10 | WebView Android ? | Chrome Android Full support Yes | Edge Mobile No support No | Firefox Android
Full support
33
| Opera Android ? | Safari iOS Full support 9.3 | Samsung Internet Android Full support Yes |
frame-src | Chrome Full support 25 | Edge Full support 14 | Firefox Full support 23 | IE No support No | Opera Full support 15 | Safari Full support 7 | WebView Android Full support Yes | Chrome Android Full support Yes | Edge Mobile ? | Firefox Android Full support 23 | Opera Android ? | Safari iOS Full support 7.1 | Samsung Internet Android Full support Yes |
img-src | Chrome Full support 25 | Edge Full support 14 | Firefox Full support 23 | IE No support No | Opera Full support 15 | Safari Full support 7 | WebView Android Full support Yes | Chrome Android Full support Yes | Edge Mobile ? | Firefox Android Full support 23 | Opera Android ? | Safari iOS Full support 7.1 | Samsung Internet Android Full support Yes |
manifest-src | Chrome Full support Yes | Edge No support No | Firefox Full support 41 | IE No support No | Opera Full support Yes | Safari No support No | WebView Android Full support Yes | Chrome Android Full support Yes | Edge Mobile No support No | Firefox Android Full support 41 | Opera Android ? | Safari iOS No support No | Samsung Internet Android Full support Yes |
media-src | Chrome Full support 25 | Edge Full support 14 | Firefox Full support 23 | IE No support No | Opera Full support 15 | Safari Full support 7 | WebView Android Full support Yes | Chrome Android Full support Yes | Edge Mobile ? | Firefox Android Full support 23 | Opera Android ? | Safari iOS Full support 7.1 | Samsung Internet Android Full support Yes |
navigate-to | Chrome No support No | Edge No support No | Firefox No support No | IE No support No | Opera No support No | Safari No support No | WebView Android No support No | Chrome Android No support No | Edge Mobile No support No | Firefox Android No support No | Opera Android No support No | Safari iOS No support No | Samsung Internet Android No support No |
object-src | Chrome Full support 25 | Edge Full support 14 | Firefox Full support 23 | IE No support No | Opera Full support 15 | Safari Full support 7 | WebView Android Full support Yes | Chrome Android Full support Yes | Edge Mobile ? | Firefox Android Full support 23 | Opera Android ? | Safari iOS Full support 7.1 | Samsung Internet Android Full support Yes |
plugin-types | Chrome Full support 40 | Edge Full support 15 | Firefox
No support
No
| IE No support No | Opera Full support 27 | Safari Full support 10 | WebView Android Full support Yes | Chrome Android Full support Yes | Edge Mobile No support No | Firefox Android No support No | Opera Android ? | Safari iOS Full support 9.3 | Samsung Internet Android Full support Yes |
referrer | Chrome No support 33 — 56 | Edge No support No | Firefox No support 37 — 62 | IE No support No | Opera No support ? — 43 | Safari No support No | WebView Android No support 37 — 56 | Chrome Android No support 33 — 56 | Edge Mobile No support No | Firefox Android No support 37 — 62 | Opera Android No support ? — 43 | Safari iOS No support No | Samsung Internet Android Full support Yes |
report-sample | Chrome Full support 59 | Edge ? | Firefox ? | IE ? | Opera Full support 46 | Safari ? | WebView Android Full support 59 | Chrome Android Full support 59 | Edge Mobile ? | Firefox Android ? | Opera Android Full support 46 | Safari iOS ? | Samsung Internet Android Full support 7.0 |
report-to | Chrome No support No | Edge No support No | Firefox No support No | IE No support No | Opera No support No | Safari No support No | WebView Android No support No | Chrome Android No support No | Edge Mobile No support No | Firefox Android No support No | Opera Android No support No | Safari iOS No support No | Samsung Internet Android No support No |
report-uri | Chrome Full support 25 | Edge Full support 14 | Firefox Full support 23 | IE No support No | Opera Full support 15 | Safari Full support 7 | WebView Android Full support Yes | Chrome Android Full support Yes | Edge Mobile ? | Firefox Android Full support 23 | Opera Android ? | Safari iOS Full support 7.1 | Samsung Internet Android Full support Yes |
require-sri-for | Chrome Full support 54 | Edge No support No | Firefox
Full support
49
| IE No support No | Opera Full support 41 | Safari No support No | WebView Android Full support 54 | Chrome Android Full support 54 | Edge Mobile No support No | Firefox Android
Full support
49
| Opera Android Full support 41 | Safari iOS No support No | Samsung Internet Android Full support 6.0 |
sandbox | Chrome Full support 25 | Edge Full support 14 | Firefox Full support 50 | IE Full support 10 | Opera Full support 15 | Safari Full support 7 | WebView Android Full support Yes | Chrome Android Full support Yes | Edge Mobile ? | Firefox Android Full support 50 | Opera Android ? | Safari iOS Full support 7.1 | Samsung Internet Android Full support Yes |
script-src | Chrome Full support 25 | Edge Full support 14 | Firefox Full support 23 | IE No support No | Opera Full support 15 | Safari Full support 7 | WebView Android Full support Yes | Chrome Android Full support Yes | Edge Mobile ? | Firefox Android Full support 23 | Opera Android ? | Safari iOS Full support 7.1 | Samsung Internet Android Full support Yes |
strict-dynamic | Chrome Full support 52 | Edge No support No | Firefox Full support 52 | IE No support No | Opera Full support 39 | Safari No support No | WebView Android Full support 52 | Chrome Android Full support 52 | Edge Mobile No support No | Firefox Android No support No | Opera Android Full support 39 | Safari iOS No support No | Samsung Internet Android Full support 6.0 |
style-src | Chrome Full support 25 | Edge Full support 14 | Firefox Full support 23 | IE No support No | Opera Full support 15 | Safari Full support 7 | WebView Android Full support Yes | Chrome Android Full support Yes | Edge Mobile ? | Firefox Android Full support 23 | Opera Android ? | Safari iOS Full support 7.1 | Samsung Internet Android Full support Yes |
upgrade-insecure-requests | Chrome Full support 43 | Edge
No support
No
| Firefox Full support 42 | IE No support No | Opera Full support 30 | Safari Full support 10.1 | WebView Android Full support 43 | Chrome Android Full support 43 | Edge Mobile No support No | Firefox Android Full support 42 | Opera Android Full support 30 | Safari iOS Full support 10.3 | Samsung Internet Android Full support 4.0 |
worker-src | Chrome
Full support
59
| Edge No support No | Firefox Full support 58 | IE No support No | Opera Full support 48 | Safari No support No | WebView Android
Full support
59
| Chrome Android
Full support
59
| Edge Mobile No support No | Firefox Android Full support 58 | Opera Android Full support 48 | Safari iOS No support No | Samsung Internet Android Full support 7.0 |
Legend
- Full support
- Full support
- No support
- No support
- Compatibility unknown
- Compatibility unknown
- Experimental. Expect behavior to change in the future.
- Experimental. Expect behavior to change in the future.
- Non-standard. Expect poor cross-browser support.
- Non-standard. Expect poor cross-browser support.
- Deprecated. Not for use in new websites.
- Deprecated. Not for use in new websites.
- See implementation notes.
- See implementation notes.
- User must explicitly enable this feature.
- User must explicitly enable this feature.
A specific incompatibility exists in some versions of the Safari web browser, whereby if a Content Security Policy header is set, but not a Same Origin header, the browser will block self-hosted content and off-site content, and incorrectly report that this is due to a the Content Security Policy not allowing the content.