The idea of the Content Security Policy was to tell web-browsers what content to load from where. This means that attackers should not be able to inject their own code if, for example, 'unsafe-inline'
was not explicitly allowed (which is not the best thing to do).
Google also released a CSP Evaluator, which is designed to find possible mistakes in your policy. With the default settings, the tool recommends using the 'strict-dynamic'
policy for 'script-src'
. The idea behind it is that you write a loader for whichever JavaScript sourcees you require and forbid everything else.
What is considered the "correct" way to implement such a loader? Should the loader be written yourself (see below for example) or should a tool be used to create such a loader? (Please note that this question is not asking for a specific tool recommendation)
var imported = document.createElement('script');
imported.src = '/path/to/imported/script';
document.head.appendChild(imported);
My website currently has the following policy:
default-src 'none';
img-src 'self';
style-src 'self' https://stackpath.bootstrapcdn.com 'sha256-bviLPwiqrYk7TOtr5i2eb7I5exfGcGEvVuxmITyg//c=';
script-src https://use.fontawesome.com https://code.jquery.com https://cdnjs.cloudflare.com https://stackpath.bootstrapcdn.com;
base-uri 'none';
form-action 'none';
frame-ancestors 'none';
Google's tool suggested the following:
Host whitelists can frequently be bypassed. Consider using
'strict-dynamic'
in combination with CSP nonces or hashes.
As such, I want to implement a loader to load these JS frameworks and I want to know how to best approach this issue.
An immediate answer is that as long as the script you're dynamically loading (/path/to/imported/script
) is hosted in a domain that you've already whitelisted in script-src
, you don't have to modify your CSP or change your loader -- everything will work as expected.
However, a broader problem is that your script-src
whitelist includes domains that host Javascript which can be used by an attacker who finds a markup injection bug in your application to bypass your CSP. For example, https://cdnjs.cloudflare.com
hosts Angular (https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.2/angular.min.js
) which can be used by an attacker to convert an HTML injection into arbitrary script execution (here is a paper about this).
The suggestion in the CSP Evaluator tool is to switch your application to rely on a script-src
which uses CSP nonces instead of the whitelist. To do this you would need to follow the process outlined at https://csp.withgoogle.com/docs/strict-csp.html -- basically, make sure that every <script>
element has a correct nonce
attribute which changes for every page load, or instead use CSP3 hashes for static scripts.
Your CSP would then look like:
... script-src 'nonce-[random-value]' 'strict-dynamic' 'unsafe-inline' https:; ...
If you use 'strict-dynamic'
, your script loader does not have to change because browsers will automatically trust scripts added to your page via programmatic APIs such as appendChild()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With