Skip to content

[Bug]: @sapiom/fetch loses Request.__sapiom metadata when cloning input #690

Description

@Kewe63

Affected package or area

@sapiom/fetch

Affected version, release, or commit

@sapiom/fetch 0.5.0, commit d7d480a

Environment

  • Node.js: v24.14.1
  • Package manager and version: pnpm 10.34.3 via Corepack
  • Operating system: WSL2 / Linux 5.15.167.4-microsoft-standard-WSL2 x86_64
  • Runtime or framework (if relevant): native Fetch API / Request

Minimal reproduction and steps

Reproduction code sample:

const r = new Request("https://example.test/public");
r.__sapiom = { enabled: false };

const copy = new Request(r);

console.log(JSON.stringify({
  original: r.__sapiom,
  cloned: copy.__sapiom ?? null,
  clonedHasOwn: Object.prototype.hasOwnProperty.call(copy, "__sapiom"),
}, null, 2));

Steps:

  1. Create a Request object.
  2. Attach __sapiom = { enabled: false } to it.
  3. Clone it with new Request(request), matching what @sapiom/fetch does internally.
  4. Check whether the cloned request still has __sapiom.

Actual output from the reproduction:

{
  "original": {
    "enabled": false
  },
  "cloned": null,
  "clonedHasOwn": false
}

The metadata is lost during cloning, so @sapiom/fetch reads no per-request override after new Request(input, init).

Expected behavior

The documented per-request override should be honored for Request inputs.

When a request is created like this:

const publicRequest = new Request("/api/public");
(publicRequest as any).__sapiom = { enabled: false };
await fetch(publicRequest);

@sapiom/fetch should bypass Sapiom authorization/payment handling for that single request.

The metadata should be read from the original Request before cloning, or copied onto the cloned request before interceptors run.

Actual behavior

@sapiom/fetch clones the input with new Request(input, init) before reading __sapiom.

Native Request cloning does not preserve custom properties, so __sapiom is lost. As a result, a request with __sapiom = { enabled: false } is treated as if no per-request override was provided, and the request can still continue through Sapiom authorization/payment handling instead of being bypassed.

Logs, screenshots, and additional context

Relevant code:

  • packages/fetch/src/fetch.ts documents Request.__sapiom per-request overrides, including { enabled: false }.
  • packages/fetch/src/fetch.ts clones the input with new Request(input, init) before reading (request as any).__sapiom.
  • packages/fetch/src/interceptors.ts also reads metadata from the cloned request.

I checked open issue/PR searches for __sapiom / enabled and did not find an open duplicate.

Acknowledgements

  • I searched existing open and closed issues for this problem.
  • This report does not describe a suspected security vulnerability; I will use the Security Policy for private reporting.
  • I removed secrets, credentials, personal data, and other sensitive information from this report.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingneeds-triageAwaiting maintainer review and classification

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions