sentry-javascript: @sentry/vue breaks Google Analytics CORS policy

Is there an existing issue for this?

How do you use Sentry?

Sentry Saas (sentry.io)

Which package are you using?

@sentry/vue

SDK Version

7.14.0

Framework Version

7.14.0

Link to Sentry event

No response

Steps to Reproduce

  1. Add Sentry to vue app main.js:
import * as Sentry from '@sentry/vue'; 
import { Integrations } from '@sentry/tracing'; 

if (process.env.NODE_ENV === 'production') {
  Sentry.init({
    vm,
    dsn: 'https://12345@12345.ingest.sentry.io/12345',
    integrations: [
      new Integrations.BrowserTracing({
        routingInstrumentation: Sentry.vueRouterInstrumentation(router),
        tracingOrigins: [
          'localhost',
          'example.com',
          'example2.com',
          /^\//,
        ],
      }),
    ],
    tracesSampleRate: 0.05,
  });
}
  1. Implement analytics.js form of Google Analytics code… This part isn’t super important, all you have to know is that OUR code does not handle the ajax request (obviously, if you’ve ever used Google Analytics this makes sense). Instead, you interact with ga object provided by Google For example…
window.ga('create', '12345', 'auto');
window.ga('set', 'title', title);
window.ga('send', 'pageview', { page: document.location.pathname, title });
  1. After firing a pageview event, look in the browser and you will see ga trying to make a CORS request…
image

if you look at the exact reason it fails, its because Google responds with Access-Control-Allow-Origin: * but the request itself is using withCredentials: include

Access to XMLHttpRequest at ‘https://www.google-analytics.com/j/collect?v=1&_v=j97&a=xxxxxxxx&t=pageview&_s=1&dl=URLSTUFF’ from origin ‘https://www.example.com’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: The value of the ‘Access-Control-Allow-Origin’ header in the response must not be the wildcard ‘*’ when the request’s credentials mode is ‘include’. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

I just thought what could “wrap” these requests which might be modifying them. I disabled sentry in main.js and the analytics requests now work perfectly

Expected Result

I honestly have no idea even WHAT is happening, or why Sentry would need to modify withCredentials on xmlhttprequests… maybe that’s not even happening, but but is triggering this error indirectly

The expected result should be google analytics should work normally, like when sentry is not loaded

Actual Result

The actual way I found this is by looking at the error pasted above in chrome dev tools console. You will see the ‘initiator’ file of the error. Instead of analytics.js being the initiator (which youd expect), I noticed it was a babel chunk js file… When I clicked either of these 2 exceptions below it brings me to Sentry code, which is telling me that whatever code Sentry is wrapping is breaking the way Google needs it to work

image

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 17 (9 by maintainers)

Commits related to this issue

Most upvoted comments

Ahhh!! Great thinking with realizing its also in the query string. Thank you!!! 🎉

I will do that now but that totally makes sense thats the problem so I’ll close this pre-emptively

By looking at the google analytics URLs which get blocked with the CORS error, they indeed have “mydomain” included somewhere in the query string, and there is the “bagage” header in the request.

That’s probably what’s causing the CORS error.

I think that the Sentry documentation could be improved about this (about /^// - how does this even work if match is done against full string URL including domain and I suppose schema too)

Agreed. I’ll open up an issue in our docs repo to track this. Fwiw, we’re going to replace tracingOrigins with tracePropagationTargets (already introduced it in our Node SDK) in the near future so we’ll need to overhaul documentation anyway. However, I’ll add this point anyway as it’s relevant for both options.