nonce
GuideContent-Security-Policy
is enabled.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.
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:
<script nonce="rAnd0m"> doWhatever(); </script>
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:
<script> thisWillNotExecute(); </script>
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.
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:
<style nonce="rAnd0m"> .alert { color: red; } </style>
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.
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.
<script src="https://code.jquery.com/jquery-3.7.1.min.js" nonce="rAnd0m" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
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:
<script nonce="#request.nonce#"> var id = #url.id# </script>
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:
<script nonce="rAnd0m"> var id = doSomethingBad() </script>
As you can see we just threw away all of the cross site scripting protections of CSP by improperly using the nonce.
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.
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.
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:
bin2hex(openssl_random_pseudo_bytes(32))
import secrets nonce = secrets.token_urlsafe(32)
generateSecretKey('aes')
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.
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).
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.
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.