Skip to content

v12 does not remove react-native for pnpm users — optional peer is still auto-installed (re: #383) #507

Description

@valeporti

Summary

#383 was closed as "addressed in v12.0.0", but v12 does not remove react-native from the tree for pnpm users. Making react-native-url-polyfill an optional peer does not stop pnpm from installing it, because pnpm has had auto-install-peers enabled by default since v8. The result is that a pure Node.js backend still gets the entire React Native + Metro subtree, including packages with unpatchable high-severity advisories.

I verified this on pubnub@12.0.3 with pnpm 10.9.0 before concluding it, so this isn't a stale-lockfile artifact.

Reproduction

// package.json — a plain Node service, no React Native anywhere
{ "dependencies": { "pubnub": "12.0.3" } }
$ pnpm install
$ pnpm why image-size

dependencies:
pubnub 12.0.3
└─┬ react-native-url-polyfill 2.0.0 peer
  └─┬ react-native 0.84.0 peer
    └─┬ @react-native/community-cli-plugin 0.84.0
      └─┬ metro 0.83.7
        └── image-size 1.2.1

The resulting lockfile entry shows pnpm resolving the optional peer and recording it as an optional dependency of pubnub:

pubnub@12.0.3(react-native-url-polyfill@2.0.0(react-native@0.84.0(@babel/core@7.29.0)(react@19.2.4))):
  dependencies:
    agentkeepalive: 3.5.3
    # ...
  optionalDependencies:
    react-native-url-polyfill: 2.0.0(react-native@0.84.0(...))

Deleting the lockfile and re-resolving from scratch produces the same result, so it is the resolution behaviour and not inherited state.

Why this matters beyond package size

metro pulls in image-size, which currently carries two high-severity DoS advisories:

Both are <=2.0.2, and 2.0.2 is the latest published version of image-size — so there is no patched release to move to. pnpm audit reports Patched versions: <0.0.0. This fails pnpm audit --audit-level=high on every CI run for any pnpm-based Node consumer of the SDK, with no upgrade path.

This is the concern @Kaspik raised in #383 shortly before it was closed, and it is now worse: the advisory in question has no fix available at all.

What does not work as a consumer-side fix

For completeness, on pnpm 10.9 these do not prevent the install:

  • pnpm.ignoredOptionalDependencies: ["react-native-url-polyfill"] — in either package.json or pnpm-workspace.yaml
  • pnpm.peerDependencyRules.ignoreMissing: ["react-native-url-polyfill", "react-native"]

The npm-style overrides workaround @yo1dog posted in #383 does have a pnpm equivalent (aliasing the edge to an empty local package), but it is fragile — in our case it broke a multi-stage Docker build, because the stub directory has to exist at install time in every build context. Turning off auto-install-peers globally is the only config lever that reliably works, and that is far too blunt to be a reasonable ask.

Suggested fix

Ship the Node build without a dependency edge to react-native-url-polyfill at all, rather than relying on peer-optionality that package managers are free to resolve. Options that would work:

  1. Separate entry points / packages so the Node build never references the polyfill (the original suggestion in SDK package too large for Lambda, contains frontend frameworks #383).
  2. Use the platform-native URL in the Node build. URL and URLSearchParams have been Node globals since v10, and v12 already requires >=22, so the polyfill has nothing to contribute on that platform.

Related

Environment

  • pubnub 12.0.3 (also reproduced on 10.2.9, where the polyfill is a hard dependencies entry)
  • pnpm 10.9.0, autoInstallPeers: true (pnpm's default since v8)
  • Node 22

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions