Skip to content

Do not mutate options object in wrapped fetch to attach headers #18828

@amcsi

Description

@amcsi

Problem Statement

When calling fetch, Sentry's underlying wrapped fetch gets called, and it mutates the options object to inject the baggage and sentry-trace headers. It's good that the headers get injected, but it's not good that the options object gets mutated for these reasons:

  1. The caller may be expecting the passed object to not be mutated, because maybe it's a statically constant object that they want to reuse for other things, and they don't want the values tampered with.
  2. If the options object is frozen (with Object.freeze(), or implicitly when immer's produce() is called to assemble the options object), then injecting the headers fails silently (unless debug mode is enabled for Sentry) due to it being unable to mutate the object. I ran into this issue not long ago: The sentry-trace header is not being sent with fetch requests #3547 (comment)

Solution Brainstorm

I propose it would be better to clone the object instead to alleviate the above issues.

Additional Context

Here's where the mutation happens:

options.headers = headers;

And here's some logic you can see where before we get to the mutation logic, at the function call that eventually takes you to the mutation logic, there's no return value reading, so really the code was explicitly written with the intent of having the options object mutated (with the headers). This would be fine if the object were deep cloned first:

By the way, this may or may not be happening with the XHR instrumentation as well; though at a short glance it looks like the SentryWrappedXMLHttpRequest object has .setRequestHeader() get called on it, but that's a request class instance, so it's obviously meant to be stateful and only used for a single request, so that should be fine.

Priority

React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding +1 or me too, to help us triage it.

Metadata

Metadata

Assignees

No one assigned

    Projects

    Status

    Waiting for: Product Owner

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions