New developers to ownCloud sometimes wonder why JavaScript code embedded in HTML templates is not executed in most browsers. The answer behind this lies in the Content-Security-Policy (CSP), a very powerful and interesting web security feature.

While ownCloud uses CSP since version 5.0.0, which was released in March 2013 and was thus one of the first larger deployed open-source projects using it, a lot of persons have yet not really heard of the implications and advantages of the CSP. Hopefully this post can help to shed some light on it.

It shall be noted that this post is not meant as a complete web application security primer and intentionally neglects some other very important security aspects to make the subject easier to understand.

A very short introduction to XSS

A crucial part of being able to understand CSP is to have a rough understanding of the security risks that it is able to prevent. Let’s thus shortly talk about one of the most common web application security issues: Cross-Site-Scripting (XSS).

When you develop a web application you usually very often take user input, do some stuff with it and return a response to the user. For example the following PHP script will ask the users for their name and display it back to the user:

<html>
<?php
if(isset($_GET['name'])) {
	echo(sprintf('Hello <font color="green">%s</font>!', $_GET['name']));
	exit();
}
?>

<form method="GET">
	<input type="text" name="name" placeholder="Enter your name"/>
	<input type="submit"/>
</form>
</html>

If you are a security aware developer you might have already spotted the security problem: The user input is not sanitized before displaying it back to the user and thus this is vulnerable to so called Cross-Site-Scripting.

No worries if you still didn’t get it. Let’s just consider what would happen if a user would provide something like <script>alert(1)</script> to the input box. The output would now look like the following:

<html>
Hello <font color="green"><script>alert(1)</script></font>!
</html>

The problem here is that when the user now opens the page the embedded JavaScript would get executed and show a popup box to the user:

Alert box created using Cross-Site-Scripting

Obviously, the popup is not the problem here but the fact that with JavaScript you might be able to do nearly whatever you want in the browser on the same domain. For example if the user is authenticated as administrator an attacker might create new users or do some other pretty nasty stuff.

Developers can prevent this by encoding all user output appropriately, so that for example a < would get inserted as &lt; in the HTML. However, developers are humans too and humans are unfortunately very error prone. Especially errors like this can happen very quickly.

How the Content-Security-Policy can help

The Content-Security-Policy, or short CSP, is an open standard implemented by most browser vendors (i.e. everything except Internet Explorer) that allows websites to define additional security policies that are aimed to prevent attack vectors such as Cross-Site-Scripting.

When you accessing an ownCloud instance the browser will receive a Content-Security-Policy header with a script-src value of 'self' 'unsafe-eval', this will tell the browser to not execute any JavaScript not served from a dedicated JavaScript file from the same domain. Thus inline JavaScript, which allows attack vectors like the above one, will simply get ignored by browsers.

For developers this means that you have to embed all JavaScript snippets in dedicated files, this is however also considered best-practise and allows ownCloud to automatically minify your JavaScript files as well as add proper caching headers.

Ongoing improvements

When it comes to security the best option is a secure by default model. This is also in what we at ownCloud believe and a reason behind many of the recent security optimizations that we have done recently.

Most prominently in regard to the CSP will be the fact that in versions before 8.1 (our next major release) all sites used the same default policy which was not as strict as we wanted too. Thus with ownCloud 8.1 we hardened the default policy and added a possibility for applications using the AppFramework to modify it. As a developer you are now able to allow for example JavaScript resources from another domain:

<?php



public function index() {
	$response = new TemplateResponse('activity', 'list', []);
	$csp = new ContentSecurityPolicy();
	$csp->addAllowedScriptDomain('www.owncloud.org');
	$response->setContentSecurityPolicy($csp);
	return $response;
}

While our current policy is already very strict it is still not perfect and we are striving to harden it further in the future by disallowing inline stylesheets as well as forbidding eval-like constructs in JavaScript.

This however also means that with 8.1 it is not possible anymore to define a default policy in config.php using the custom_csp_policy configuration switch. We believe that there is not a lot of sense in maintaining yet another switch which was only introduced as a workaround.

A world without XSS?

The more applications that are deploying the Content-Security-Policy, the more secure the overall security of the web will get. However, CSP can at the moment not be considered a panacea against every injection like attack. While an attacker might not be able anymore to inject JavaScript they will still be able to inject arbitrary HTML elements.

While this sounds not too scary let’s think about it one moment. What would happen if an attacker inserts a faked login form? How many users would realize that it is actually a malicious form?

If you are interested in these topics I can only highly recommend you to take a look at Postcards from the post-XSS world.