====== Ubuntu - CSP (Content Security Policy) ======
The **Content-Security-Policy** HTTP response header helps you reduce XSS risks on modern browsers by declaring what dynamic resources are allowed to load via a HTTP Header.
**NOTE**: It is known that having both **Content-Security-Policy** and **X-Content-Security-Policy** or **X-Webkit-CSP** causes unexpected behaviours on certain versions of browsers. Please avoid using deprecated **X-*** headers.
----
===== Directive Reference =====
The Content-Security-Policy header value is made up of one or more directives (defined below), multiple directives are separated with a semicolon ;
^Directive^Example Value^Description^
|default-src|'self' cdn.example.com|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|'self' js.example.com|Defines valid sources of JavaScript.|
|style-src|'self' css.example.com|Defines valid sources of stylesheets.|
|img-src|'self' img.example.com|Defines valid sources of images.|
|connect-src|'self'|Applies to XMLHttpRequest (AJAX), WebSocket or EventSource. If not allowed the browser emulates a 400 HTTP status code.|
|font-src|font.example.com|Defines valid sources of fonts.|
|object-src|'self'|Defines valid sources of plugins, e.g. , or .|
|media-src|media.example.com|Defines valid sources of audio and video, e.g. HTML5 , elements.|
|frame-src|'self'|[DEPRECIATED]Defines valid sources for loading frames. child-src is preferred over this deprecated directive.|
|sandbox|allow-forms allow-scripts|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 allow-popups, allow-modals, allow-orientation-lock, allow-pointer-lock, allow-presentation, allow-popups-to-escape-sandbox, and allow-top-navigation.|
|report-uri|/some-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).|
|child-src|'self'|Defines valid sources for web workers and nested browsing contexts loaded using elements such as and .|
|form-action|'self'|Defines valid sources that can be used as a HTML action.|
|frame-ancestors|'none'|Defines valid sources for embedding the resource using . Setting this directive to 'none' should be roughly equivalent to X-Frame-Options: DENY.|
|plugin-types|application/pdf|Defines valid MIME types for plugins invoked via and . To load an you must specify application/x-java-applet.|
|base-uri| |Restricts the URLs that can be used to specify the document base URL.|
----
===== 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 separated with the exception of **'none'** which should be the only value.
Domain patterns can contain both protocol and ports if you want to be specific: **http://*.example.com:8080**
^Source Value^Example^Description^
|*|img-src *|Wildcard, allows any URL except data: blob: filesystem: schemes.|
|'none'|object-src 'none'|Prevents loading resources from any source.|
|'self'|script-src 'self'|Allows loading resources from the same origin (same scheme, host and port).|
|data:|img-src 'self' data:|Allows resources to be inlined with base64 (e.g. Base64 encoded images).|
|domain.example.com|img-src domain.example.com|Allows loading resources from the specified domain name.|
|*.example.com|img-src *.example.com|Allows loading resources from any subdomain under example.com.|
|https://cdn.com|img-src https://cdn.com|Allows loading resources only over HTTPS matching the given domain.|
|https:|img-src https:|Allows loading resources only over HTTPS on any domain. Forces HTTPS.|
|'unsafe-inline'|script-src 'unsafe-inline'|Allows inline and and onclick elements. This can be further secured by specifying a hash of the code.|
|'unsafe-eval'|script-src 'unsafe-eval'|Allows unsafe dynamic code evaluation such as JavaScript eval().|
----
===== How it Works =====
The **default-src**, as the name suggests, sets the default source list for the remaining directives. If a directive isn't explicitly included in the CSP header, it will fall back to using the values in the **default-src** list.
All directives follow the same pattern:
* **self** is used to refer to the current domain.
* one or more URLs can be specified in a space-separated list.
* **none** indicates that nothing should be loaded for a given directive e.g. object-src 'none' indicates that no plugins—such as Flash or Java—should be loaded.
----
===== Content-Security-Policy Examples =====
Here a few common scenarios for content security policies:
==== Allow everything but only from the same origin ====
At its simplest, we could define a CSP to load resources only from the current domain as follows:
default-src 'self';
----
==== Only Allow Scripts from the same origin ====
script-src 'self';
----
==== Allow Same Origin, Google Analytics, and Google AJAX CDN ====
script-src 'self' www.google-analytics.com ajax.googleapis.com;
----
==== Starter Policy ====
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). It is a good starting point for many sites.
default-src 'none'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self';
----
==== 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.
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:;
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.
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.
An example to block only passive mixed content:
Content-Security-Policy: img-src https: data:; font-src https: data:; media-src https:;
An example to block only active mixed content:
Content-Security-Policy: script-src https:; style-src https:; object-src https:; connect-src https:; frame-src https:;
----
===== Prevent Clickjacking =====
The established way of preventing clickjacking involves the use of the header X-Frame-Options (see: [[https://www.owasp.org/index.php/Clickjacking_Defense_Cheat_Sheet|Clickjacking_Defense_Cheat_Sheet]]). However, CSP 2.0 has a new directive **frame-ancestors**.
To prevent all framing of your content use:
Content-Security-Policy: frame-ancestors 'none'
To allow for your site only, use:
Content-Security-Policy: frame-ancestors 'self'
To allow for trusted domain (my-trusty-site.com), do the following:
Content-Security-Policy: frame-ancestors my-trusty-site.com
**WARNING:** Not supported in all browsers yet.
Also, keep in mind the following (from the [[https://w3c.github.io/webappsec/specs/content-security-policy/#frame-ancestors-and-frame-options|CSP Spec]]):
The frame-ancestors directive MUST be ignored when monitoring a policy, and when a contained in a policy defined via a meta element.
In other words, this will not work when CSP is in a **** tag, and will not work when using **Content-Security-Policy-Report-Only**.
When a report is generated, the **blocked-uri** will only have a value if it is the same origin as the page.
----
===== Re-factoring inline code =====
By default CSP disables any unsigned JavaScript code placed inline in the HTML source, such as this:
with 'app.js' containing the 'var foo = "314"' code.
The inline code restriction also applies to inline event handlers, so that the following construct will be blocked under CSP:
This should be replaced by `addEventListener' calls:
document.getElementById("button1").addEventListener('click', doSomething);
Variable assignment in inline scripts. Rather than do this: