-
-
Notifications
You must be signed in to change notification settings - Fork 399
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Hash-based CSP support #814
Comments
Ok, in doing some initial poking around I see |
Curious if anyone is willing to voice opinions on this? I find this idea appealing, because it would allow decoupling the otherwise static FE bundle from depending on dynamic nonce injection. That's nice because that re-opens the door to CDN based hosting. |
If you are willing to create a PR for this, we would be open for it. You would need to implement it, create tests and the documentation for it. I guess the implementation should be relatively easy, though this approach wouldn't work where a StyleSheet is linked (dynamic). Also, your implementation shouldn't include any hashing libaries by default; the user would need to be able to pass/configure them, so they aren't installed for someone who doesn't use this feature. |
This might be of some use to you |
Thanks for sharing that, will take a look. Starting tomorrow I'm going to be away for approx. the next 2 weeks but intend to resume looking at this when I get back. If anyone has enough interest to take a crack meanwhile, that'd be great! More when I'm back :) |
Unfortunately I don't think something like this is scalable. You would need to list a hash of every style block you add. The CSP header would become huge in a large application. |
Thanks @dav-is, yeah I was basically starting to reach the same conclusion. |
@onpaws I'm pretty sure new <style> tags need to follow the CSP, but if js adds |
Interesting approach @onpaws . Curious if anyone knows of other solutions for using jss in environments where dynamically rendering html tag content is not an option (e.g. when serving from a CDN). Currently, I'm setting I did find that dynamically rendering the var nonce = Array.from(document.getElementsByTagName('meta')).slice(0).find((tag) => tag.httpEquiv === 'Content-Security-Policy').content.match(/script-src.*'nonce-(.*?)'/)[1]
var meta = document.createElement('meta')
meta.setAttribute('property', 'csp-nonce')
meta.setAttribute('content', nonce)
document.head.appendChild(meta) Doesn't that kind of undermine the whole point of CSP rules and nonces? I.e. if malicious code on the client can read the existing nonces, what point does it serve? Presumably if something can inject malicious css, it can also read the existing nonce and convince the browser to interpret the css? Or am I missing something here? |
Caveat: I haven't actually tried this yet. If CloudFlare is an option, it sounds like the Worker product might allow rendering dynamic HTML tag content. |
That does sound very odd. Any chance you could share a sample? Curious to repro. |
The below html file will log the <!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Security-Policy" content="base-uri 'self'; object-src 'none'; script-src 'self' 'nonce-oXyH+9nGiPmPt5/tBRP2zw=='; default-src 'self'">
<meta charset="utf-8">
</head>
<body>
<script nonce="oXyH+9nGiPmPt5/tBRP2zw==">
var nonce = Array.from(document.getElementsByTagName('meta')).slice(0).find((tag) => tag.httpEquiv === 'Content-Security-Policy').content.match(/script-src.*'nonce-(.*?)'/)[1]
console.log(nonce)
</script>
</body>
</html> I need to read up on the CSP spec more to really understand why this seeming vulnerability exists. I would have hoped that browsers only allow a nonce to be used once, so that malicious code couldn't reuse an existing nonce to inject malicious code. But that doesn't seem to be the case. |
I’m not 100% sure I’m understanding you right, and I’m not claiming to be a super CSP expert, but here are my two cents. The way I understand CSP, its effects are performed before JavaScript runs on the page. Because it’s value is delivered as a header, it is read before the actual page content. Does that make sense? Or am I maybe misunderstanding you? |
Yeah, you're spot on, but a few additional points might illustrate the vulnerability I'm talking about (I think... I might be misunderstanding how CSP mitigates injection attacks)
If all of the above is true (the Content-Security-Policy is set via meta tag, the browser does not complain about reusing nonces, and an injection attack will often have access to the DOM), then an injection attack could read the nonce, add it to the script/style tag of the malicious payload it is trying to execute, and append the tag to the DOM. CSP in this case would not make an injection attack substantially more difficult. |
I've never set CSP via meta tag, I'm curious what the use case is, because your assessment makes sense -it seems it would make it less effective. According to this |
Shout out to the lovely humans who did some great CSP work so far and even shipped documentation. I was recently able to get CSP working on my project thanks to this, cheers.
So this is a great start, but because my app is 100% static [1] I'd prefer to calculate everything ahead of time and avoid the dynamic nonce injection/Helmet approach, if possible. In other words I'd like to support this CSP flavor - do a search for hash-algorithm.
Thus I'm now trying to understand the basis by which JSS injects these
<style>
tags, e.g.First I thought if it were possible to force JSS to inject a single
<style>
tag into the document, I could hash that ahead of time. Then I read the material-ui docs which discuss performance reasons for splitting styles across multiple tags, and now I'm curious to learn about the tradeoffs and configurability here.A possible but clunky alternative is that according the Google CSP evaluator we can define multiple hashes inside one style-src string.
style-src 'self' 'sha256-z124...' 'sha256-2g7e...';
Perhaps this is all a terrible idea and that's OK. Still, even if academic, I'd love to learn what it'd take to arrange this. Hope I'm making sense and thanks for a lovely library either way!
[1] My app is based on CRA and doesn't need to support user-uploaded stuff -- in theory, we should be able to keep everything static, which will enable "dumb" CDN hosting -- fastest page loads at the lowest possible cost.
The text was updated successfully, but these errors were encountered: