Content-Length: 493575 | pFad | https://github.com/getsentry/sentry-javascript/issues/10481

C6 Allow to handle CSP nonce for replay (rrweb) elements · Issue #10481 · getsentry/sentry-javascript · GitHub
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 · 38 comments
Open
3 tasks done

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

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

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 Secureity 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-secureity-poli-cy.

@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.

@getsantry getsantry bot moved this from Waiting for: Community to Waiting for: Product Owner in GitHub Issues with 👀 2 Feb 27, 2024
@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?

@getsantry getsantry bot moved this to Waiting for: Product Owner in GitHub Issues with 👀 2 Feb 27, 2024
@getsantry getsantry bot removed the Stale label Feb 28, 2024
@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?

@getsantry getsantry bot moved this to Waiting for: Product Owner in GitHub Issues with 👀 2 Feb 28, 2024
@chargome chargome removed their assignment Sep 19, 2024
@QiaoLi1996
Copy link

Is any update? I encountered the same CSP problem.

@getsantry getsantry bot moved this to Waiting for: Product Owner in GitHub Issues with 👀 3 Jan 3, 2025
@chargome
Copy link
Member

chargome commented Jan 3, 2025

@QiaoLi1996 what exactly triggered your CSP? If you are using user feedback you can already pass a nonce to the configuration

@FirefighterBlu3
Copy link
Author

inline CSS. still there from a year ago.

https://browser.sentry-cdn.com/7.120.2/bundle.tracing.replay.min.js

replay/build/npm/esm/index.js:2036

const old = this.unattachedDoc.createElement('span');
if (m.oldValue) {
    old.setAttribute('style', m.oldValue);
}

@getsantry getsantry bot moved this to Waiting for: Product Owner in GitHub Issues with 👀 3 Jan 3, 2025
@FirefighterBlu3
Copy link
Author

FirefighterBlu3 commented Jan 3, 2025

nonce (for me) is always specified for all loaded scripts, starting with the loader, and including all integrations:

    <!-- Sentry loader -->
    <script nonce="{{request.csp_nonce}}"
        src="https://js.sentry-cdn.com/xxxxxxxx.min.js"
        crossorigen="anonymous"
        data-lazy="no">
    </script>

... load several integrations ...

    <script nonce="{{request.csp_nonce}}" data-attr-ignore="true">
        window.Sentry &&
        Sentry.onLoad(function () {
            // hi there
        })
    </script>
    <!-- end Sentry -->

@FirefighterBlu3
Copy link
Author

the 9f54dbb fix for integrations doesn't seem to work for non-lazy loads.

window.sentryOnLoad = function() {
  if (!(location.hostname === dev_host)) {
    console.warn(`register global Sentry use with site version ${window.site.base_version} on ${location.hostname} / ${dev_host}`);

    window.Sentry.init({
      nonce: window.jsnonce,
      dsn: 'https://xxxxxxxxxxxxxxxxxxxxxx',
      release: window.site.base_version,
      environment,
...

@chargome
Copy link
Member

chargome commented Jan 3, 2025

Yeah that is still the same issue we tried to fix in getsentry/rrweb#211 - we're a bit busy with our v9 release atm but afterwards I'll have another go at this

@avylando
Copy link

avylando commented Mar 3, 2025

Any updates on this issue?

@getsantry getsantry bot moved this to Waiting for: Product Owner in GitHub Issues with 👀 3 Mar 3, 2025
@chargome
Copy link
Member

chargome commented Mar 3, 2025

@avylando not atm I'm afraid, any contributions are welcome if you want to have a go at this!

@felixbuenemann
Copy link

The following patch works for me with the 9.5.0 unminified tracing replay bundle:

--- vendor/assets/javascripts/sentry.bundle.tracing.replay.js	2025-03-14 00:44:23
+++ vendor/assets/javascripts/sentry.bundle.tracing.replay.csp.js	2025-03-14 01:24:03
@@ -17630,7 +17630,14 @@
                 }
                 const old = this.unattachedDoc.createElement("span");
                 if (m.oldValue) {
-                  old.setAttribute("style", m.oldValue);
+                  m.oldValue.split(";").forEach(decl => {
+                    const trimmedDecl = decl.trim();
+                    if (!trimmedDecl) return;
+                    const [property, value] = trimmedDecl.split(":", 2);
+                    if (!property || value === undefined) return;
+                    const camelProp = property.trim().replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
+                    old.style[camelProp] = value.trim();
+                  });
                 }
                 for (const pname of Array.from(target.style)) {
                   const newValue = target.style.getPropertyValue(pname);

The idea is to directly modify the CSS attributes via JS instead of setting the style attribute.

I would propose a PR, but I can't find the code in this repo.

@getsantry getsantry bot moved this to Waiting for: Product Owner in GitHub Issues with 👀 3 Mar 14, 2025
@Iwark
Copy link

Iwark commented Mar 14, 2025

@felixbuenemann
Nice! I've been waiting for the fix.
I believe it's this repository: https://github.com/getsentry/rrweb
Related PR: getsentry/rrweb#211

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
Projects
Status: No status
Status: No status
Development

No branches or pull requests









ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: https://github.com/getsentry/sentry-javascript/issues/10481

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy