Tip of the tree Blink now has CSP 1.1 script nonce support: https://t.co/AnVl6llNMG #blink #chrome #contentsecuritypolicy
— Joel Weinberger (@metromoxie) May 16, 2013
This left a lot people confused. Clearly I was excited about it, but why? So I thought I'd clarify here.
For those of you who don't know, Content Security Policy (CSP) is a browser mechanism for helping to eliminate cross-site scripting (XSS) vulnerabilities in web sites. Now, there are a variety of caveats to that statement, namely that CSP requires developers to code in a more limited style, requires the server to send specific headers, and ultimately still allows developers to shoot themselves in the foot. But, for now, let's assume it makes the world a better place if used1.
One of the limitations of CSP that needs to be enforced for it to effectively block XSS attacks is the requirement that the page contains absolutely no inline scripts. This means absolutely no script tags with code, e.g.
<script>alert('foobar');</script>. It also means no sneaky inline handlers or
<button onclick="alert('foobar');">click me!</button>or
Why this requirement? Well, one of the insights of the creators of CSP is that the way XSS often happens is when a web server puts untrusted content on a page, and sanitizes the content incorrectly (or does not sanitize it at all). Then, even though the content is not expected to contain a script, the bad guy inserts a script which is served up to unsuspecting users. So CSP prevents these scripts for executing, and therefore if a bad guy tries to insert them, they simply will not execute.
By the same token, CSP allows external scripts to be loaded (i.e.
<script src="some/path/here.html"></script>), but only from an explicitly chosen set of servers. Thus, a bad guy could insert a script tag that loads a script from a URL, but the he would be limited to only a small set of servers, ostensibly controlled by the developer. So getting an XSS attack this way will be much, much more difficult.
Enter the idea of a script whitelist. The creators of the latest version of CSP, CSP 1.1, realized that we don't want to ban all inline scripts; we want to ban all unknown inline scripts. But how do we specify known, whitelisted scripts? This is where nonces come into play.
A nonce is a use-once, randomly generated number, that is unforgeable. Practically speaking, that just means it's a big, random number. What CSP 1.1 introduces is the ability for a server to list a set of newly generated nonces every time a page is loaded that can be used to whitelist scripts. Then, when the page is loaded, the developer may include inline scripts, but only if she specifies the script with a valid nonce. Say the server specifies with the page that
9253884is a valid nonce. CSP 1.1 allows a developer to write the following:
<script nonce="9253884"> alert('foobar'); </script>The clever part here is that the inline script specifies a secret that only the good guy could know. That is, a bad guy could still try to insert
<script>tags on the page, but because the nonce is not guessable, his script will be rejected by the browser. And there you have it: the benefits of CSP while allowing inline scripts. There are actually a couple other uses of CSP 1.1 nonces, but I'll leave them out here because this is definitely the main use.
In short, while Chrome has had CSP for a while now, we're trying to get up to the CSP 1.1 spec so that we can provide developers and users with even more awesome security and usability benefits. The implementation of this nonce support in the latest development version of Blink is just a small part in a much bigger picture, but I hope it will go a long way in helping developers and spreading the adoption of CSP.
Clarification: I skipped over this, but was quickly called out on Twitter. Script nonces can additionally be used to include external scripts that are not from whitelisted sources. That is, CSP requires that all external scripts are only loaded from a set of whitelisted servers. However, if you specify a valid nonce, you can bypass this requirement.
Update on 2013-07-23: Because the nonce spec is not quite settled, we've moved it behind a run time experimental flag for Content Security Policy features. You can still test it out, but you just need to be sure to run Chrome with that flag. You can enabled going to chrome://flags and selecting "enable" beneath "Enable experimental Web Platform features."
1 In the past, I've actually done some research on the topic of CSP limitations, and there are a bunch. On the whole, though, I definitely believe it to be a boon for the Web. For the ultimate skeptic turned believer, see Adam Barth's blog post on CSP. ↩