Skip to content
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

Allow to handle CSP nonce for replay (rrweb) elements #10481

Open
3 tasks done
FirefighterBlu3 opened this issue Feb 2, 2024 · 28 comments
Open
3 tasks done

Allow to handle CSP nonce for replay (rrweb) elements #10481

FirefighterBlu3 opened this issue Feb 2, 2024 · 28 comments
Labels
Package: replay Issues related to the Sentry Replay SDK Package-Meta: Loader Type: Bug

Comments

@FirefighterBlu3
Copy link

FirefighterBlu3 commented Feb 2, 2024

Is there an existing issue for this?

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://aba269c1f55349d89eadb788807dce2f@o413851.ingest.sentry.io/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 :}

@FirefighterBlu3
Copy link
Author

...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 <style> element.

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.

@AbhiPrasad
Copy link
Member

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.

// Create a `script` tag with provided SDK `url` and attach it just before the first, already existing `script` tag
// Scripts that are dynamically created and added to the document are async by default,
// they don't block rendering and execute as soon as they download, meaning they could
// come out in the wrong order. Because of that we don't need async=1 as GA does.
// it was probably(?) a legacy behavior that they left to not modify few years old snippet
// https://www.html5rocks.com/en/tutorials/speed/script-loading/
var _currentScriptTag = _document.scripts[0];
var _newScriptTag = _document.createElement(_script);
_newScriptTag.src = _sdkBundleUrl;
_newScriptTag.crossOrigin = 'anonymous';
// Once our SDK is loaded
_newScriptTag.addEventListener('load', function() {
try {
// Restore onerror/onunhandledrejection handlers
_window[_onerror] = _oldOnerror;
_window[_onunhandledrejection] = _oldOnunhandledrejection;
// Add loader as SDK source
_window.SENTRY_SDK_SOURCE = 'loader';
var SDK = _window[_namespace];
var oldInit = SDK.init;
// Configure it using provided DSN and config object
SDK.init = function(options) {
var target = _config;
for (var key in options) {
if (Object.prototype.hasOwnProperty.call(options, key)) {
target[key] = options[key];
}
}
oldInit(target);
};
sdkLoaded(callbacks, SDK);
} catch (o_O) {
console.error(o_O);
}
});
_currentScriptTag.parentNode.insertBefore(_newScriptTag, _currentScriptTag);

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.

@getsantry
Copy link

getsantry bot commented Feb 27, 2024

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 🥀

@getsantry getsantry bot added the Stale label Feb 27, 2024
@reesericci
Copy link

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.

@AbhiPrasad
Copy link
Member

@reesericci - PRs are welcome! Loader script here: https://github.com/getsentry/sentry-javascript/blob/develop/packages/browser/src/loader.js

@reesericci
Copy link

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?

@mydea
Copy link
Member

mydea commented Feb 28, 2024

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!

@reesericci
Copy link

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?

@AbhiPrasad
Copy link
Member

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

@getsantry
Copy link

getsantry bot commented Mar 22, 2024

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 🥀

@getsantry getsantry bot added the Stale label Mar 22, 2024
@rob101
Copy link

rob101 commented Mar 29, 2024

This issue occurs when mutations.js finds an existing inline style but doesn't reapply the nonce:

image

@scottohara
Copy link

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.

@billyvg
Copy link
Member

billyvg commented Jun 18, 2024

@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

@billyvg
Copy link
Member

billyvg commented Jun 27, 2024

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.

@scottohara
Copy link

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.

@FirefighterBlu3
Copy link
Author

FirefighterBlu3 commented Jun 28, 2024 via email

@shehi
Copy link

shehi commented Jun 28, 2024 via email

@rob101
Copy link

rob101 commented Jul 27, 2024

@billyvg is a fix planned for this / a workaround now available? thanks

@mydea mydea changed the title CSP inline style errors using the loader Allow to handle CSP nonce for rrweb elements Jul 29, 2024
@mydea mydea changed the title Allow to handle CSP nonce for rrweb elements Allow to handle CSP nonce for replay (rrweb) elements Jul 29, 2024
@chargome chargome self-assigned this Jul 29, 2024
@chargome chargome added the Package: replay Issues related to the Sentry Replay SDK label Jul 29, 2024
@billyvg
Copy link
Member

billyvg commented Jul 30, 2024

@billyvg is a fix planned for this / a workaround now available? thanks

Yes, a fix is planned! @chargome will be taking this on shortly.

@jdelStrother
Copy link

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?

@chargome
Copy link
Member

chargome commented Aug 2, 2024

@jdelStrother I'll look into it

@chargome
Copy link
Member

chargome commented Aug 6, 2024

Quick update, I had a closer look at this one today and it seems that we're facing two distinct issues:

  1. The feedback integration does not apply nonces to <script /> and <style /> tags (not a problem, we'll just set it).
  2. 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.

@TimVerheul
Copy link

Quick update, I had a closer look at this one today and it seems that we're facing two distinct issues:

  1. The feedback integration does not apply nonces to <script /> and <style /> tags (not a problem, we'll just set it).
  2. 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.

any update on point 2?

@chargome
Copy link
Member

@TimVerheul didn't find a feasible fix for that yet: getsentry/rrweb#211 (comment)

@chargome chargome removed their assignment Sep 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Package: replay Issues related to the Sentry Replay SDK Package-Meta: Loader Type: Bug
Projects
Status: No status
Status: No status
Development

No branches or pull requests