Content Security Policy Cheat Sheet

Content Security Policy (CSP) is an important standard by the W3C that is aimed to prevent a broad range of content injection attacks such as cross-site scripting (XSS).

= Introduction =

Content Security Policy (CSP) is an effective "defense in depth" technique to be used against content injection attacks. It is a declarative policy that informs the user agent what are valid sources to load from.

Since, it was introduced in Firefox version 4 by Mozilla, it has been adopted as a standard, and grown in adoption and capabilities.

This document is meant to provide guidance on how to utilize CSP under a variety of situations to address a variety of concerns.

= References =

Specifications of the CSP standard can be found the following locations:
 * Latest Revision - https://w3c.github.io/webappsec/specs/content-security-policy/
 * Latest Version (CSP2) - http://www.w3.org/TR/CSP2/
 * CSP 1.0 - http://www.w3.org/TR/2012/CR-CSP-20121115/

= CSP Basics =

CSP consists of a series of directives. CSP has also evolved over two major revisions. Most browsers support 1.0, and adoption of CSP2 has been incremental.

HTTP Headers
The following are headers for CSP.


 * Content-Security-Policy : W3C Spec standard header. Supported by Firefox 23+, Chrome 25+ and Opera 19+
 * Content-Security-Policy-Report-Only : W3C Spec standard header. Supported by Firefox 23+, Chrome 25+ and Opera 19+, whereby the policy is non-blocking ("fail open") and a report is sent to the URL designated by the report-uri directive. This is often used as a precursor to utilizing CSP in blocking mode ("fail closed")
 * DO NOT use X-Content-Security-Policy or X-WebKit-CSP. Their implementations are obsolete (since Firefox 23, Chrome 25), limited, inconsistent, and incredibly buggy.

Directives
The following is a listing of directives, and a brief description.

CSP 1.0 Spec

 * connect-src (d) - restricts which URLs the protected resource can load using script interfaces. (e.g. send method of an XMLHttpRequest object)
 * font-src (d) - restricts from where the protected resource can load fonts
 * img-src (d) - restricts from where the protected resource can load images
 * media-src (d) - restricts from where the protected resource can load video, audio, and associated text tracks
 * object-src (d) - restricts from where the protected resource can load plugins
 * script-src (d) - restricts which scripts the protected resource can execute. Additional restrictions against, inline scripts, and eval. Additional directives in CSP2 for hash and nonce support
 * style-src (d) - restricts which styles the user may applies to the protected resource. Additional restrictions against inline and eval.
 * default-src - Covers any directive with (d)
 * frame-src - restricts from where the protected resource can embed frames. Note, deprecated in CSP2
 * report-uri - specifies a URL to which the user agent sends reports about policy violation
 * sandbox - specifies an HTML sandbox policy that the user agent applies to the protected resource. Optional in 1.0

New in CSP2

 * form-action - retricts which URLs can be used as the action of HTML form elements
 * frame-ancestors - indicates whether the user agent should allow embedding the resource using a frame, iframe, object, embed or applet element, or equivalent functionality in non-HTML resources
 * plugin-types - restricts the set of plugins that can be invoked by the protected resource by limiting the types of resources that can be embedded
 * base-uri - restricts the URLs that can be used to specify the document base URL
 * child-src (d) - governs the creation of nested browsing contexts as well as Worker execution contexts

= CSP Sample Policies =

Basic CSP Policy
This policy will only allow resources from the originating domain for all the default level directives, and will not allow inline scripts/styles to execute. If your application and function with these restrictions, it drastically reduces your attack surface having this policy in place, and will work with most modern browsers.

The most basic policy assumes:
 * all resources are hosted by the same domain of the document
 * there are no inlines or evals for scripts and style resources

Content-Security-Policy: default-src 'self'

To tighten further, one can do the following:

Content-Security-Policy: default-src 'none'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self';

This policy allows images, scripts, AJAX, and CSS from the same origin, and does not allow any other resources to load (eg. object, frame, media, etc). (see http://content-security-policy.com/)

Mixed Content Policy
In order to prevent mixed content (resources being loaded over http, from a document loaded over https), one can use the value "https:" as a directive value.

For instance:

Content-Security-Policy: default-src https:; connect-src https:; font-src https: data:; frame-src https:; img-src https: data:; media-src https:; object-src https:; script-src 'unsafe-inline' 'unsafe-eval' https:; style-src 'unsafe-inline' https:;

This is what was used at Twitter, Oct 2014. The policy prevents mixed content, allows for scheme "data:" in font-src and img-src, allows for unsafe-inline and unsafe-eval for script-src, and unsafe-inline for style-src. (see: https://twittercommunity.com/t/blocking-mixed-content-with-content-security-policy/26375)

Mixed Content has two categories: Active and Passive. Passive content consists of "resources which cannot directly interact with or modify other resources on a page: images, fonts, audio, and video for example", whereas active content is "content which can in some way directly manipulate the resource with which a user is interacting." (http://www.w3.org/TR/2014/WD-mixed-content-20140722)

Content-Security-Policy: img-src https: data:; font-src https: data:; media-src https:;

This is an example to block only passive mixed content.

Content-Security-Policy: script-src https:; style-src https:; object-src https:; connect-src https:; frame-src https:;

This is an example to block only active mixed content.

= CSP Cheat Sheet - Guide for main technologies =

This section summarizes the implementation and/or support for CSP in different technologies (either acting as Client or Server). See below the details.

Google Chrome

Google Chrome based web applications and theme uses a manifest file named manifest.json. There is a section in the manifest file where the developer can declare the CSP directives. For further details, please refer to Content Security Police for Google Chrome.

{ // Required "manifest_version": 2, "name": "My Extension", "version": "versionString",

// Recommended "default_locale": "en", "description": "A plain text description", "icons": {...},

// Pick one (or none) "browser_action": {...}, "page_action": {...},

// Optional "author": ..., "automation": ..., "background": { // Recommended "persistent": false }, "background_page": ..., "chrome_settings_overrides": {...}, "chrome_ui_overrides": { "bookmarks_ui": { "remove_bookmark_shortcut": true, "remove_button": true } },  "chrome_url_overrides": {...}, "commands": ..., "content_pack": ..., "content_scripts": [{...}], "content_security_policy": "policyString", "converted_from_user_script": ..., "current_locale": ..., "devtools_page": ..., "externally_connectable": { "matches": ["*://*.example.com/*"] }, "file_browser_handlers": [...], "homepage_url": "http://path/to/homepage", "import": ..., "incognito": "spanning or split", "input_components": ..., "key": "publicKey", "minimum_chrome_version": "versionString", "nacl_modules": [...], "oauth2": ..., "offline_enabled": true, "omnibox": { "keyword": "aString" }, "optional_permissions": ..., "options_page": "aFile.html", "options_ui": ..., "page_actions": ..., "permissions": [...], "platforms": ..., "plugins": [...], "requirements": {...}, "sandbox": [...], "script_badge": ..., "short_name": "Short Name", "signature": ..., "spellcheck": ..., "storage": { "managed_schema": "schema.json" }, "system_indicator": ..., "tts_engine": ..., "update_url": "http://path/to/updateInfo.xml", "web_accessible_resources": [...]}

Apache

It is required to add lines to the httpd.conf configuration file, or inside .htaccess files or virtual host sections. Also, it is required to enable mod_headers, and after inserting the lines according to your specific needs, restart Apache. The headers below are good examples to add in the files (change/modify it properly):

Header unset Content-Security-Policy Header add Content-Security-Policy "default-src 'self'" Header unset X-Content-Security-Policy Header add X-Content-Security-Policy "default-src 'self'" Header unset X-WebKit-CSP Header add X-WebKit-CSP "default-src 'self'"

WordPress

Most of the configuration can be done in Apache, however, Wordpress has a plugin that allows developers/administrator to set up their own custom policies. The plugin however is not update for 2 years. Use it carefully. A workaround can be the creation or modification of the file htaccess under wp-admin directory.

An example:

 Header set Content-Security-Policy "default-src 'self'; img-src 'self' data: http: https: *.gravatar.com; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline' http: https: fonts.googleapis.com; font-src 'self' data: http: https: fonts.googleapis.com themes.googleusercontent.com;" 

nginx

For nginx, it is required to edit the nginx.conf file.


 * 1) config to don't allow the browser to render the page inside an frame or iframe


 * 1) and avoid clickjacking http://en.wikipedia.org/wiki/Clickjacking

add_header X-Frame-Options SAMEORIGIN;
 * 1) if you need to allow [i]frames, you can use SAMEORIGIN or even set an uri with ALLOW-FROM uri # https://developer.mozilla.org/en-US/docs/HTTP/X-Frame-Options


 * 1) when serving user-supplied content, include a X-Content-Type-Options: nosniff header along with the Content-Type: header,


 * 1) to disable content-type sniffing on some browsers.


 * 1) https://www.owasp.org/index.php/List_of_useful_HTTP_headers


 * 1) currently suppoorted in IE > 8 http://blogs.msdn.com/b/ie/archive/2008/09/02/ie8-security-part-vi-beta-2-update.aspx


 * 1) http://msdn.microsoft.com/en-us/library/ie/gg622941(v=vs.85).aspx

add_header X-Content-Type-Options nosniff;
 * 1) 'soon' on Firefox https://bugzilla.mozilla.org/show_bug.cgi?id=471020


 * 1) This header enables the Cross-site scripting (XSS) filter built into most recent web browsers.


 * 1) It's usually enabled by default anyway, so the role of this header is to re-enable the filter for


 * 1) this particular website if it was disabled by the user.

add_header X-XSS-Protection "1; mode=block";
 * 1) https://www.owasp.org/index.php/List_of_useful_HTTP_headers


 * 1) with Content Security Policy (CSP) enabled(and a browser that supports it(http://caniuse.com/#feat=contentsecuritypolicy),


 * 1) you can tell the browser that it can only download content from the domains you explicitly allow


 * 1) http://www.html5rocks.com/en/tutorials/security/content-security-policy/


 * 1) https://www.owasp.org/index.php/Content_Security_Policy


 * 1) I need to change our application code so we can increase security by disabling 'unsafe-inline' 'unsafe-eval'


 * 1) directives for css and js(if you have inline css or js, you will need to keep it too).

add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://ssl.google-analytics.com https://assets.zendesk.com https://connect.facebook.net; img-src 'self' https://example.com https://example1.com; style-src https://example.com; font-src https://example.com; frame-src https://example.com; object-src 'none'"; server { listen 443 ssl default deferred; server_name .forgott.com; ssl_certificate the_path_of_your_certificate.crt; ssl_certificate_key the_path_of_your_key.key;
 * 1) more: http://www.html5rocks.com/en/tutorials/security/content-security-policy/#inline-code-considered-harmful

Django

Django recently introduced a package with a number a collection of models, views and middlewares to aid secure Django based projects. The installation of this model can be done through from Python packages repository: pip install django-security Also, the the latest development version, install from django-security repository on GitHub: git clone https://github.com/sdelements/django-security.git cd django-security sudo python setup.py install For each Djangon’s application, the settings.py file must be modified.

== INSTALLED_APPS = (   ...    'security',    ...    ) ==

Middleware modules can be added to MIDDLEWARE_CLASSES list in settings file. Particularly, it is our interesting the ContentSecurityPolicyMiddleware. It sends Content Security Policy (CSP) header in HTTP response.:

== MIDDLEWARE_CLASSES = ( ... 'security.middleware.DoNotTrackMiddleware', ==

= Authors and Primary Editors =

Neil Mattatall - neil[at]owasp.org Denis Mello - ddtaxe

= Other Cheatsheets =