Content Security Policy (CSP)
Quick Reference Guide


strict-dynamic in CSP

The strict-dynamic source list keyword allows you to simplify your CSP policy by favoring hashes and nonces over domain host lists.

A strict-dynamic Example

Here is an example Content-Security-Policy that uses strict-dynamic:

script-src 'nonce-r@nd0m' 'strict-dynamic';default-src 'self';

Now we can simply use a nonce to load our scripts:

<script src="/script-loader.js" nonce="r@nd0m"></script>

The key super power of strict-dynamic is that it will allow /script-loader.js to load additional scripts via non-"parser-inserted" script elements.

So how do you create a non-"parser-inserted" script element? Here's an example:

	var s = document.createElement('script');
	s.src = "https://cdn.example.com/some-script-you-need.min.js";
	document.body.appendChild(s);

You can also use other mechanisms to create a script loader, such as webpack, RequireJS, head.js, yepnope.js, etc.

Dealing with Unsupported Browsers

Since this is a new feature of CSP (CSP Level 3), if someone is using an older browser that may only have CSP Level 2 support, using the above policy the request to load a script from cdn.example.com would be blocked. Support for nonce would still work in CSP Level 2 browsers, but not in CSP Level 1.

Thankfully the authors of CSP Level 3 considered this, and have a clever workaround. When strict-dynamic is used, browsers that support it will ignore the following source list expressions:

In fact you might see something like this in your developer tools console:

content security policy: ignoring “'unsafe-inline'” within script-src: ‘strict-dynamic’ specified
content security policy: ignoring “http:” within script-src: ‘strict-dynamic’ specified
content security policy: ignoring “https:” within script-src: ‘strict-dynamic’ specified
content security policy: ignoring “'unsafe-eval'” within script-src: ‘strict-dynamic’ specified

So our script can be made backwards compatable by doing something like this:

script-src 'nonce-r@nd0m' 'strict-dynamic' https: 'self';default-src 'self';

Above we have added 'self' to allow loading of /script-loader.js and we have added https: to allow loading of https://cdn.example.com/some-script-you-need.min.js

You may notice that by adding https: we are allowing any domain to load a script, you could be more specific if you wanted to. In our example the following would be better:

script-src 'nonce-r@nd0m' 'strict-dynamic' cdn.example.com 'self';default-src 'self';

If we had an inline script block then we could consider adding 'unsafe-inline' to the policy to allow it to load on CSP Level 1 Browsers. You'll need to balance the compexity of your policy vs the bredth of browsers that you want to support.

On older browsers you may see something like this:

the source list for content security policy directive 'script-src' contains an invalid source: ''strict-dynamic''. it will be ignored.

You can also ignore such a message.

What directives support strict-dynamic?

You can use strict-dynamic in a script-src or default-src directive. When it is in the default-src it only applies to loading of scripts.

Browser Support for strict-dynamic

The strict-dynamic directive was added to CSP Level 3. It is currenlty only supported in Chrome and Firefox.

It is not supported at all in Internet Explorer, you need to use the Edge browser instead.