Content Security Policy: What are We Waiting For?

The Web Application Security Working Group of the W3C has created a standard for web security called Content Security Policy (CSP). Currently on version two with a version three in the works, CSP has been implemented by the majority of browsers and offers a strong defensive layer against XSS. Unfortunately, web developers seem reluctant to use the policy. Based on recent research, only about two percent of the most popular million websites include CSP. This is a shame as CSP not only offers easy implementation and powerful protection but its use promotes best practices in web development.

Cross site scripting (XSS) is a particularly thorny problem. Any site that displays data input by users opens itself to this vulnerability, making it possible for an attacker to run malicious code within the context of the site, code that can steal session tokens, carry out transactions, and cause all sorts of damage. It is possible to filter malicious user input to avoid XSS, but attackers have bypassed filters, leading to an arms race of ever more clever filters and bypasses. CSP provides significant protection against XSS and other threats, but not a panacea, at least not until all browsers implement the standard.

To mitigate XSS, CSP enables site owners to restrict browser behavior, enforcing a white list of content sources that the browser will trust, making it extremely difficult for an attacker to get their malicious scripts to execute.

Configuring CSP

Site owners configure this white list of trusted sources through a CSP policy defined in an HTTP header. The CSP HTTP header value is a plain-text, semicolon delimited list of directives. Each directive includes the directive name followed by a space-delimited list of paths. The header applies the policy to an individual page. Think of the page as a security context that encompasses all content within it. Depending on need, a developer can craft custom policies per page or use the same policy on every page.

Content-Security-Policy: script-src

This simple policy tells the browser to only execute scripts downloaded from and, but not from any other sources. Even if an attacker managed to insert a script tag pointing to, the browser would refuse to execute it.

CSP also supports several useful keywords. For example, adding the keyword ‘self’ to the script-src directive enables browsers to execute scripts from the site itself.

Eliminating Inline Scripts and eval()

Most importantly, the browser will not execute inline scripts, which prevents the vast majority of XSS attacks. The notion of inline here covers both script blocks and event handlers within HTML element attributes. While this restricts developers, it really just promotes the best practice of unobtrusive JavaScript, meaning keeping a clean separation between HTML and JavaScript by moving all JavaScript into script files. Event handlers can be easily added in code rather than through HTML attributes.

While the standard provides a way to override this restriction by adding the ‘unsafe-inline’ keyword to the script-src policy, this really should be avoided as it effectively eliminates almost all of the value of CSP.

CSP version 2 offers an additional alternate for inline script. It supports inline script blocks with a nonce tag that matches a nonce value in the script-src directive. Several such blocks could be added to a page. Again, this is less secure than avoiding inline scripts all together.

Content-Security-Policy: script-src nonce-WFNQcIGJSOCnmt00THCK

< script nonce="WFNQcIGJSOCnmt00THCK">
/* inline script that for some reason cannot be moved to script file */

CSP eliminates yet another vector for XSS attacks by preventing browsers from executing the eval function even when called within permitted content sources. The eval function executes strings, which poses a risk if the string contains any user input. Again, CSP does allow bypassing this protection by adding the ‘unsafe-eval’ keyword to the script-src directive, but this likewise is discouraged. (The limitation on eval applies as well to other JavaScript functions that can execute strings such as setTimeout, setInterval, and Function.)

The CSP Directives

CSP supports several other directives in addition to script-scr that can further lock down a site to prevent potential attacks.

style-src Allowed sources for style sheets.
img-src Allowed sources for images.
connect-src Allowed paths for XHR and WebSocket requests.
font-src Allowed sources for fonts.
object-src Allowed sources for plugins such as Flash.
media-src Allowed sources for audio and video.
frame-src Allowed sources for loading frames. Deprecated in version 2 of the standard. Use child-src.
child-src Allowed sources for loading frames. New in version 2.
frame-ancestors The sites allowed to load the page as a frame. Applies to <frame>, <iframe>, , and <applet> tags. Useful to prevent clickjacking.
default-src Default values for all directives ending in -src. The default is overridden whenever a specific src directive is specified.
base-uri Limits which URLs can be used in a page’s <base> element.
form-action Allowed paths for action attribute of <form> tags.
plugin-types The types of plugins that the browser may load for the page.
sandbox Imposes iframe-like sandbox on the page, preventing popups, plugins, scripts, and forms.
upgrade-insecure-requests Instructs browser to convert HTTP links into HTTPS.
report-uri A url to which the browser will post client-side policy failures.

Meta Tag

In addition to specifying CSP policies via HTTP headers, the standard supports defining policy in meta tags as in the example below. However, this approach is less secure since an attacker who manages to alter page content might find a way to alter the meta tag to enable their own exploit. Moreover, the policy will not apply to any content preceding the meta tag.

<meta http-equiv="Content-Security-Policy" content="script-src">

Path Matching and Wildcards

Path matching rules are quite straightforward. A domain name without a path, such as, matches all files served from the host. A path ending in a forward slash, such as, matches all files within that path and its sub paths. Paths that do not end with a slash, such as, match only the one specific file.

To make policy definitions more flexible, the CSP standard allows for wildcards in paths.

* Matches all content sources other than blob:, data: and filesystem:
* Matches any subdomain of
*:// Matches any protocol scheme* Matches any port (without the * the path by default matches the standard port of the protocol, meaning either 80 or 443)
https: Matches any domain but only with protocol scheme HTTPS

Defense in Depth

CSP should be considered an important new layer in a defense in depth strategy rather than a single solution for web security. XSS remains a threat for users of browsers that do not implement the standard. Moreover, you can never be sure that user input saved through one web application is not resurfaced through another one of your organization’s sites. Continue to apply XSS filters to all user input both when stored and displayed.


CSP is easy to implement for new sites. Begin with the strictest policy and ease up only as needed.

For existing sites, particularly larger, more complex sites, gaining the full benefit of CSP might prove difficult, especially if there are inline script blocks, attribute-based event handlers, and resources pulled from many sources. CSP supports an additional HTTP header, Content-Security-Policy-Report-Only, that eases the pain of finding policy violations within your site. Add this header rather than the standard CSP header so the browser will post each violation to the URL specified in the report-uri directive, enabling you can track and resolve. (See and for CSP violation tracking tools.) For guidance, read about the experiences of Twitter and Dropbox.

Supporting Tools and Libraries

Adding CSP headers to pages is straight-forward as all popular web servers and server-side web frameworks provide mechanisms for adding HTTP headers to responses. Here is a simple example in Asp.Net:

HttpContext.Response.AddHeader("Content-Security-Policy", "scipt-src ‘self’");

In addition, there are libraries available focused on HTTP security-related headers that include support for CSP.

Asp.Net NWebsec
Django Django-CSP
Java headlines (mutliple security headers)
Salvation (specific to CSP)
Node.js helmut
PHP php-csp
Ruby on Rails secureheaders

Making it even easier, the site provides an online tool for generating CSP headers. And my colleagues at Shape Security have created an online validator at to assure you’ve gotten your policy correct. So what are we waiting for?


Supported Browsers

Presentation by Adam Barth,

Reference Guide

Mozilla Reference Guide

OWASP Summary

Tutorial by Mike West

Dropbox’s Experience

Twitter’s Experience

I'm the Director of Threat Solutions at Shape Security, a top 50 startup defending the world's leading websites and mobile apps against malicious automation. Request our 2017 Credential Spill Report at to get the big picture of the threats we all face. See my LinkedIn profile at and follow me on Twitter at

Posted in HTTP Headers, Web Security

Leave a Reply

Please log in using one of these methods to post your comment: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: