The Content-Security-Policy HTTP header provides fine-grained control over the locations from which resources on a site can be loaded.
The main problem this article focuses on is Cross-site scripting (XSS) attacks. These are generally due to a lack of control and awareness of the sources from which site resources are loaded. This problem gets more difficult to manage as sites become larger and more complex and increasingly rely on third-party resources such as JavaScript libraries.
CSP can also help to fix other problems, which are covered in other articles:
Implementing a robust CSP is the best way to prevent XSS vulnerabilities.
The primary benefit of CSP comes from disabling the use of unsafe inline JavaScript. Inline JavaScript, whether reflected or stored, enables improperly-escaped user inputs to generate code that is interpreted by the web browser as JavaScript. By using CSP to disable inline JavaScript, you can eliminate almost all XSS attacks against your site.
Disabling inline JavaScript means that all JavaScript must be loaded from external files via elements with src attributes. Inline event handler attributes, such as onclick , and JavaScript inserted directly inside tags will fail to work. Furthermore, CSP can also disable internal stylesheets (inside tags) and inline styles (using the style attribute).
Therefore, design websites carefully to ensure that CSP causes less problems and becomes easier to implement.
CSP can also be used to provide granular control over:
Note: Before implementing any actual CSP with the Content-Security-Policy header, you are advised to first test it out using the Content-Security-Policy-Report-Only HTTP header. This allows you to see if any violations would have occurred with that policy. This test requires the use of report-to (or the deprecated report-uri ), as explained below.
Keep the following points in mind:
Note: > report-to is preferred over the deprecated report-uri ; however, both are still needed because report-to does not yet have full cross-browser support.
svg> use href="/images/icons.svg#icon"/> svg>
Disable unsafe inline/eval and only allow loading of resources (images, fonts, scripts, etc.) over HTTPS:
Content-Security-Policy: default-src https:
Do the same thing, but with a element:
meta http-equiv="Content-Security-Policy" content="default-src https:" />
Disable the use of unsafe inline/eval and allow everything else except plugin execution:
Content-Security-Policy: default-src *; object-src 'none'
Disable unsafe inline/eval and only load resources from same-origin with the exception of images, which can be loaded from https://i.imgur.com . This also disables the execution of plugins:
Content-Security-Policy: default-src 'self'; img-src 'self' https://i.imgur.com; object-src 'none'
Disable unsafe inline/eval scripts and plugins, load only scripts and stylesheets from same-origin, allow fonts to be loaded from https://fonts.gstatic.com , and allow image loading from same-origin and https://i.imgur.com . Sites should aim for policies like this:
Content-Security-Policy: default-src 'none'; font-src https://fonts.gstatic.com; img-src 'self' https://i.imgur.com; object-src 'none'; script-src 'self'; style-src 'self'
Allow legacy sites to load scripts safely, with an increase level of trust provided by a nonce:
script nonce="2726c7f26c"> const inline = 1; // … script>
Content-Security-Policy: script-src 'strict-dynamic' 'nonce-2726c7f26c'
Don't implement the policy yet; only report the violations that would have occurred:
Reporting-Endpoints: csp-endpoint="https://example.com/csp-reports" Content-Security-Policy-Report-Only: default-src https:; report-uri /csp-violation-report-endpoint/; report-to csp-endpoint;
Disable resource loading and embedding. APIs should use a policy like this:
Content-Security-Policy: default-src 'none'; frame-ancestors 'none'