sentry-javascript
sentry-javascript copied to clipboard
CSP inline style errors using the loader
Is there an existing issue for this?
- [X] I have checked for existing issues https://github.com/getsentry/sentry-javascript/issues
- [X] I have reviewed the documentation https://docs.sentry.io/
- [X] I am using the latest SDK release https://github.com/getsentry/sentry-javascript/releases
How do you use Sentry?
Sentry Saas (sentry.io)
Which SDK are you using?
Sentry Browser Loader
SDK Version
7.99.0
Framework Version
No response
Link to Sentry event
No response
SDK Setup
window.sentryOnLoad = function() {
console.log(`register global Sentry use with site version ${window.site.base_version}`);
window.Sentry.init({
dsn: 'https://[email protected]/5302345',
release: window.site.base_version,
environment,
attachStacktrace: true,
// ignoreErrors: [...],
ignoreTransactions: [
'https://r.lr-ingest.io'
],
tracesSampleRate: 1.0,
replaysSessionSampleRate: 0.1,
replaysOnErrorSampleRate: 1.0,
sendDefaultPii: true,
stickySession: true,
autoSessionTracking: true,
networkDetailAllowUrls: ["anchorbooting.com", "ab-dev.blue-labs.org"],
integrations: [
// this doesn't work despite following the instructions for the Loader and key configuration (set to 7.x and perf/replay/debug enabled)
// Sentry.replayIntegration({maskAllText: false, maskAllInputs: false, blockAllMedia: false,}),
new Sentry.Integrations.HttpClient({failedRequestStatusCodes: [[400, 599]],}),
],
beforeSend(event, hint) {
setTimeout(whoops, 500);
if (event && event.extra) {
// holy hell.extra, why is event null?
event.extra['form-datum'] = grobble_form_data();
event.extra.username = window.username;
}
return event;
},
});
window.Sentry.configureScope((scope) => {
scope.setExtra("form-datum", "");
});
}
Steps to Reproduce
As soon as Sentry loads, telemetry starts being sent. This occurs:
index.js:2002 Refused to apply inline style because it violates the following Content Security Policy directive: "style-src-attr 'self' 'strict-dynamic' https://fonts.googleapis.com https://use.fontawesome.com https://maps.googleapis.com https://sentry.io https://browser.sentry.io https://browser.sentry-cdn.io https://browser.sentry-cdn.com https://js.sentry-cdn.com https://anchorbooting.com https://www.anchorbooting.com https://anchor-booting.appspot.com https://anchor-booting.uc.r.appspot.com https://ab-dev.blue-labs.org https://cdn.lr-ingest.io https://maps.googleapis.com". (newline for clarity) Either the 'unsafe-inline' keyword, a hash ('sha256-DV7YSgMWr/HY4EsViytQd0ytooqEFSst4W0YJHo8NkU='), or a nonce ('nonce-...') is required to enable inline execution. Note that hashes do not apply to event handlers, style attributes and javascript: navigations unless the 'unsafe-hashes' keyword is present.
Expected Result
No CSP errors :)
Actual Result
The CSP error :}
...Hey there. I did some searching through your docs to see if there was a way to sneak a nonce into the vanilla JS loader. Injecting the nonce is referred to in the Sveltekit content but I don't see a way to use this with the loader. Is there?
If not, here's an idea. Google maps gives us the ability to do it by adding the nonce to the URL, or, using a custom script loader. For some situations, it'll fetch the nonce from the first
The tl;dr of this, is to create a function that makes a script fragment and attaches it to the document. In the loader you do something like this:
script.type = 'text/javascript';
script.src = srcurl;
script.nonce = nonce;
...
and then you call the loader with the nonce value that by whatever means you (I) can control in my site.
My goal is to fix the execution denial of setting style inside the index.js that the loader fetches, roughly at line 2002.
if (attributeName === 'style') {
const old = unattachedDoc.createElement('span');
if (m.oldValue) {
old.setAttribute('style', m.oldValue);
}
I believe unsafe-inline will not be an option when Manivest v3 rolls out. Mv3 will actually be very intolerant in this regard.
Hey thanks for raising an issue!
My goal is to fix the execution denial of setting style inside the index.js that the loader fetches, roughly at line 2002.
The loader nor the Sentry SDK does not have any code like this. You can validate this by searching our repo for this code. See below for how the loader does injection. Are you getting a false positive here? I suspect there is another script you are using that is causing issues.
https://github.com/getsentry/sentry-javascript/blob/84baeb1847b0cd90af43ba8b29517b1b6cb24854/packages/browser/src/loader.js#L59-L101
I believe unsafe-inline will not be an option when Manifest v3 rolls out. Mv3 will actually be very intolerant in this regard.
For chrome extension we generally recommend not using the general loader init because of the problems of multiple Sentry instances on the page colliding, and instead using a client directly via the npm package. See our docs for more specific instructions.
Also, we do have general CSP guidance for the CDN bundle: https://docs.sentry.io/platforms/javascript/install/loader/#content-security-policy.
This issue has gone three weeks without activity. In another week, I will close it.
But! If you comment or otherwise update it, I will reset the clock, and if you remove the label Waiting for: Community, I will leave it alone ... forever!
"A weed is but an unloved flower." ― Ella Wheeler Wilcox 🥀
I just ran into this today, it would be really helpful if I could just inject a nonce into the Sentry init that gets passed to the style/script attributes.
@reesericci - PRs are welcome! Loader script here: https://github.com/getsentry/sentry-javascript/blob/develop/packages/browser/src/loader.js
Just looking at the script, it doesn't seem like it loads the style tags there, just the scripts - do you know where I could find those?
Just looking at the script, it doesn't seem like it loads the style tags there, just the scripts - do you know where I could find those?
The loader does not inject any style tags - it doesn't do anything with styles, actually. Which @AbhiPrasad mentioned above - I don't think this comes from the loader script, but some other library/extension probably. The Sentry Loader Script only injects the Sentry SDK, which does not have any styles!
The shadow root for the feedback widget has a <style> tag, and so there needs to be some way to pass the nonce from the loader to this feedback widget inline style. Is the feedback widget in a separate repo?
the loader does not support feedback atm - the code for the feedback widget is in https://github.com/getsentry/sentry-javascript/tree/develop/packages/feedback
This issue has gone three weeks without activity. In another week, I will close it.
But! If you comment or otherwise update it, I will reset the clock, and if you remove the label Waiting for: Community, I will leave it alone ... forever!
"A weed is but an unloved flower." ― Ella Wheeler Wilcox 🥀
This issue occurs when mutations.js finds an existing inline style but doesn't reapply the nonce:
This issue occurs when mutations.js finds an existing inline style but doesn't reapply the nonce:
Hmm, that's a great catch! I guess that makes sense. We'll look into this.
@mydea FWIW this is probably affecting anyone using popperjs/floatUI or any nonce-safe script that injects inline style (e.g. Boostrap, etc).
When the style is injected into the DOM, sentry will then mutate it but without the nonce and so it triggers a CSP error. I.e. each mouseover of a tooltip results in an error. I can try to make a repo for you but it seems otherwise fairly straightforward to reproduce.
I'll try to look into it next week! Thanks for the added detail!
Yup, keeps happening at webpack-internal:///(app-pages-browser)/node_modules/@sentry/replay/esm/index.js LINE 2051:
I also have strict CSP in place, with nonce calculated and added to request as X-Nonce header, which can easily be fetched and applied to inline scripts.
I've been trialling Sentry on a Developer plan successfully for a few months, and I decided yesterday to try out Session Replays to see whether they would be useful to me.
After following the guidance in the docs, I updated my Sentry.init() code to include the replays integration with a low sample rate (as the developer plan only includes 50 replays per month).
The docs also indicated updating my CSP to include worker-src 'self' blob:, which I did.
After 1 day, I received an email saying I had used 80% of my 5k Errors quota; and it turns out that the spike was entirely due to style-src-attr CSP errors caused by the replay script.
If this issue is proving challenging to solve properly, might I suggest you update the docs for setting up Session Replays to mention that adding style-src-attr 'unsafe-inline' may be advisable (at least temporarily?).
Unfortunately I'm now in a situation where my Sentry Developer plan will be mostly useless for the next 3 weeks until my Errors quota is replenished; and all because I simply wanted to try out Session Replays.
@scottohara Hey Scott, sorry to hear about that - I'll speak to our support staff to see what we can do. Needless to say our SDKs shouldn't be eating up your Sentry quota, hopefully it doesn't happen again, but please reach out to support if it does.
We'll look into fixing the underlying issue
Would the ideal solution here be to pass a nonce into Sentry.init() that gets passed down to our integrations (and then used as necessary, e.g. in mutation.ts)?
I've created a quick repro, you can also add something like the following:
<meta
http-equiv="Content-Security-Policy"
content="style-src 'nonce-foo1234';"
/>
Running the replay integration should throw errors with the above CSP.
Would the ideal solution here be to pass a nonce into Sentry.init()
@billyvg I can't speak for everyone here, but that solution would likely work well for us.
We are already generating a unique, per-request nonce for our CSP, so being able to pass this down to Sentry.init() would be ideal.
I too would very much like this
On Thu, Jun 27, 2024, 10:40 PM scottohara @.***> wrote:
Would the ideal solution here be to pass a nonce into Sentry.init()
@billyvg https://github.com/billyvg I can't speak for everyone here, but that solution would likely work well for us.
We are already generating a unique, per-request nonce for our CSP, so being able to pass this down to Sentry.init() would be ideal.
— Reply to this email directly, view it on GitHub https://github.com/getsentry/sentry-javascript/issues/10481#issuecomment-2196002583, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAYEW5EVXNZRI7BYDVZZELLZJTEJXAVCNFSM6AAAAABCXPGN2WVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCOJWGAYDENJYGM . You are receiving this because you authored the thread.Message ID: @.***>
Works for us as well.
On Fri, 28 Jun 2024, 13:48 David Ford, @.***> wrote:
I too would very much like this
On Thu, Jun 27, 2024, 10:40 PM scottohara @.***> wrote:
Would the ideal solution here be to pass a nonce into Sentry.init()
@billyvg https://github.com/billyvg I can't speak for everyone here, but that solution would likely work well for us.
We are already generating a unique, per-request nonce for our CSP, so being able to pass this down to Sentry.init() would be ideal.
— Reply to this email directly, view it on GitHub < https://github.com/getsentry/sentry-javascript/issues/10481#issuecomment-2196002583>,
or unsubscribe < https://github.com/notifications/unsubscribe-auth/AAYEW5EVXNZRI7BYDVZZELLZJTEJXAVCNFSM6AAAAABCXPGN2WVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCOJWGAYDENJYGM>
. You are receiving this because you authored the thread.Message ID: @.***>
— Reply to this email directly, view it on GitHub https://github.com/getsentry/sentry-javascript/issues/10481#issuecomment-2196726443, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAE7SAINVT6QADQVW4HJ2ZDZJVEQBAVCNFSM6AAAAABCXPGN2WVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCOJWG4ZDMNBUGM . You are receiving this because you commented.Message ID: @.***>
@billyvg is a fix planned for this / a workaround now available? thanks
@billyvg is a fix planned for this / a workaround now available? thanks
Yes, a fix is planned! @chargome will be taking this on shortly.
I'm also interested in being able to specify a nonce for the stylesheet injected by showReportDialog - will that be covered by @chargome's work or shall I open a separate issue?
@jdelStrother I'll look into it
Quick update, I had a closer look at this one today and it seems that we're facing two distinct issues:
- The feedback integration does not apply nonces to
<script />and<style />tags (not a problem, we'll just set it). - The replay integration (with rrweb) is setting a new style attribute on a
<span />tag which violates CSP. This can't be fixed with a nonce though since nonces can only be applied to<script />and<style />tags. I found a fix where I set all style properties directly (e.g.element.style[cssProperty] = someValue;) instead of the whole style attribute, which gets rid of the CSP error but I will need to do a bit more testing on this.
