Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google Chrome Stripping nonce values from script tags

I'm trying to add nonce values to my inline scripts to satisfy a stricter CSP. However, I am running into a weird issue where chrome is stripping the value from nonce attributes. When I curl the page, nonce values are present. This is causing the script not to be executed as it now fails the CSP test. I thought this may be due to a rogue extension, but it fails on a perfectly clean version of chrome. (Version 73.0.3683.103 on OSX) The value for the nonce is a random 256 bit base encoded string, so it should satisfy all requirements for the nonce.

Does anyone have any idea what is going on? Am I doing something wrong?

like image 596
tomciopp Avatar asked Apr 14 '19 00:04

tomciopp


1 Answers

What’s described in the question is actually expected behavior — required per the HTML spec:

https://html.spec.whatwg.org/multipage/#nonce-attributes:attr-nonce

Elements that have a nonce content attribute ensure that the crytographic nonce is only exposed to script (and not to side-channels like CSS attribute selectors) by extracting the value from the content attribute, moving it into an internal slot named [[CryptographicNonce]]

https://html.spec.whatwg.org/multipage/#nonce-attributes:dom-noncedelement-nonce

…the setter for the nonce IDL attribute does not update the corresponding content attribute. This, as well as the below setting of the nonce content attribute to the empty string when an element becomes browsing-context connected, is meant to prevent exfiltration of the nonce value through mechanisms that can easily read content attributes, such as selectors.

This behavior was added in an update to the spec at https://github.com/whatwg/html/pull/2373 (Hide nonce content attribute values); see675 https://github.com/whatwg/html/issues/2369.

To be clear: the behavior the spec requires is, if the markup source you serve over the wire has:

<script nonce=DhcnhD3khTMePgXw>...</script>

…then if you open browser devtools and use the DOM inspector, what you’ll see instead is this:

<script nonce>...</script>

That is, the DOM inspector will show no value for the nonce attribute on that script element.

More accurately: you’ll see no value for the nonce attribute on that script if the doc is served with a Content-Security-Policy header, and the browser is applying the policy in that header.

If you don’t serve the doc with a Content-Security-Policy header, or browsers don’t apply the policy from it, you’ll see nonce=DhcnhD3khTMePgXw for the script element in the inspector.

So the lack of a value for that nonce attribute in the DOM inspector actually indicates that things are working as expected. That is, it indicates the browser is checking the value for a match against any nonce-* source expressions in the Content-Security-Policy header.

The way it works inside browsers is: browsers move the nonce attribute’s value to an “internal slot” for the browser’s own use. So it stays available to the browser, but hidden from the DOM.

The reason you don’t yet see the same behavior as Chrome’s in Safari is, Safari hasn’t caught up with the spec update and implemented the requirement. But there is an open Safari bug.


To check if your browser conforms to the spec behavior, you can use the tests here:

  • https://web-platform-tests.live/content-security-policy/nonce-hiding/

And the current results for those tests in major browsers are here:

  • https://wpt.fyi/results/content-security-policy/nonce-hiding
like image 67
sideshowbarker Avatar answered Oct 15 '22 09:10

sideshowbarker