CSP Nonce ⟶ Script & Style Attribute (original) (raw)
The CSP nonce Guide
Learn how to use a CSP nonce to allow the loading and execution of a script or style tag when a Content-Security-Policy is enabled.
What is a nonce?
The word nonce can be defined as a word or phrase that is intended for use only once. If you were a spy, you might come up with a nonce as a code word to authenticate a rendezvous.
In cryptography a nonce may be used to prevent replay attacks, where the attacker captures and replays a previously used message.
The two most important things to remember when using a nonce, especially with respect to (CSP), is that we only use our nonce once (for one request), and the nonce should be so random that no one could guess it.
A CSP nonce will be a randomly generated token that we use exactly one time.
Example Script Nonce Usage
Using a nonce is one of the easiest ways to allow the execution of inline scripts in a Content Security Policy (CSP). Here's how one might use a script nonce with the CSP script-src directive:
script-src 'nonce-rAnd0m';
NOTE: We are using the phrase: rAnd0m to denote a random nonce value. You should use a cryptographically secure random token generator to generate a CSP nonce value. The random nonce value should only be used for a single HTTP request.
Now we can allow an inline <script> tag to execute by adding our random nonce value in the nonce attribute of the script tag:
What is a CSP script nonce for?
So why do we need a to add a csp nonce to every inline script block when we use CSP? The short answer is that when you enable CSP it will disable inline script tags, so code like the following will not execute:
This is because the browser doesn't know the difference between JavaScript code that you wrote and intend for the user to execute vs code that an attacker has injected into the page (for example via an XSS vulnerability). These inline script blocks are dangerous, and the script nonce attribute lets the browser know that the server intended on serving this script block if and only if the nonce attribute value in the script tag matches the nonce value in the Content-Security-Policy header.
What is a CSP style nonce?
The HTML <style> tag can also accept the nonce attribute. Because CSS styles can also be used to load or request resources or potentially execute client side code, inline style tags are also blocked by default once a CSP policy is enabled.
In order to allow a style tag to run, we can set the style tag nonce attribute like this:
And our Content-Security-Policy header would include the random style nonce value in the style-src directive, like this:
style-src 'nonce-rAnd0m';
In this case the inline style tag is allowed to run thanks to the style nonce provided.
Using a Nonce on External Scripts
You can use a CSP nonce on external scripts or stylesheets to allow them to execute. For example if we have a CSP policy similar to the following:
Content-Security-Policy: default-src 'none';script-src 'nonce-rAnd0m'
You can then add the nonce attribute to the script tag to allow jQuery to load without adding code.jquery.com to the CSP policy.
Avoid this common nonce mistake
If you are outputting variables inside a nonce protected script tag, you could cancel out the XSS protection that CSP is giving you.
For example assume you have a URL such as /example/?id=123 and you are outputting that id value from the URL in your script block:
In the above example assume that the variable token #url.id# is the id value from the query string. Now an attacker could request the URL: /example/?id=doSomethingBad(), and your application would send back:
As you can see we just threw away all of the cross site scripting protections of CSP by improperly using the nonce.
Considering Nonce vs Hash
An alternative to using a CSP nonce, is the CSP hash. There are pros and cons to using nonce vs using a hash, but both approaches allow you to allow inline script or inline CSS with CSP.
Pros of using a Nonce vs a Hash
- The nonce is smaller than the hash so the header size will be smaller
- When you change the content of the script or style block you don't need to change your nonce logic, but if you are using a hash you would need to recompute the hash whenever the script or style tag inner text changes.
Cons of using a Nonce vs a Hash
- The nonce needs to be generated dynamically, and must be different for each request, so you need to generate the CSP header programmatically.
- When using a hash the header can be defined in the web server (since it does not change), rather than at the application level.
- Since the resulting document changes every time with a nonce, it cannot be cached
How long should the nonce be?
One of the first questions you might ask yourself when implementing a content security policy script nonce, is how many characters should it be?
In general you can use the same length you might use for a session identifier, or at least 128 bits. A 128 bit nonce would be 32 characters of a hexadecimal string, or about 24 characters of a base64 encoded string.
How can you generate a nonce value?
There are many ways to generate a random value for use with a csp script nonce or style nonce. Which ever option you choose make sure that you are relying on a library that uses a cryptographically secure random generator. Depending on what programming language you use, here are a few common ways to do it:
Generate CSP Nonce With PHP
bin2hex(openssl_random_pseudo_bytes(32))
Generate CSP Nonce With Python
import secrets nonce = secrets.token_urlsafe(32)
Generate CSP Nonce in CFML / ColdFusion
generateSecretKey('aes')
Rules for Using a CSP Nonce
- The nonce must be unique for each HTTP response
- The nonce should be generated using a cryptographically secure random generator
- The nonce should have sufficient length, aim for at least 128 bits of entropy (32 hex characters, or about 24 base64 characters).
- Script tags that have a nonce attribute must not have any untrusted / unescaped variables within them.
- The characters that can be used in the nonce string are limited to the characters found in base64 encoding.
If you do need to use a variable like in the above example, you need to make sure that it has been validated. In this case we could make sure it is a valid integer. In more complex cases you would need pass the variable through an encoder that would escape javascript. For example in the Java OWASP ESAPI library the encodeJavaScript function could be used, or in CFML the encodeForJavaScript function could be used.
What if a CSP nonce doesn't make sense?
In some situations using a nonce doesn't make sense, in those cases you can use a CSP hash instead of a nonce.
There is one other workaround to this problem called unsafe-inline, but as its name suggests it is not really a good idea to use it (except in specific conditions).
Nonce Browser Support
The nonce source list directive was added to CSP Level 2. This means that support has existed since 2015 in Chrome and Firefox, Safari 10+ or Edge 15+.
Nonces are not supported at all in Internet Explorer, you need to use the Edge browser for nonce support instead.
CSP Developer Field Guide
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.
Struggling to stay on top of security advisories?
Advisory Week is a weekly roundup of all the security advisories published by the major software vendors.
