Skip to content

fix(fetch): prefer native fetch to avoid node-fetch premature close#742

Merged
orius123 merged 1 commit into
mainfrom
fix/node-fetch-premature-close
Jun 18, 2026
Merged

fix(fetch): prefer native fetch to avoid node-fetch premature close#742
orius123 merged 1 commit into
mainfrom
fix/node-fetch-premature-close

Conversation

@orius123

Copy link
Copy Markdown
Member

Related Issues

Related: nodejs/node#63989

Description

Problem

On Node 22.23.0 and 24.17.0 (the June 2026 security release, CVE-2026-48931 http.Agent fix), cross-fetch -> node-fetch@2.7.0 throws a false FetchError: ... Premature close [ERR_STREAM_PREMATURE_CLOSE] on keep-alive responses. Every SDK request runs through cross-fetch, so this breaks validateSession, key fetches, and management calls for any app on those runtimes (commonly hit via unpinned node:22 / node:24 base images). Node's built-in fetch (undici) is unaffected.

Fix

lib/fetch-polyfill.ts prefers the global fetch (undici, Node 18+) and falls back to cross-fetch only on older runtimes.

Behavior

  • Before: keep-alive responses throw ERR_STREAM_PREMATURE_CLOSE on Node 22.23.0 / 24.17.0.
  • After: requests use native fetch on Node 18+, no premature-close error. No API or config change.

Tests

  • Existing suite: 22 suites / 356 tests pass.
  • Verified against a keep-alive + chunked /v2/keys mock on Node 22.23.0 and 24.17.0: SDK getKey succeeds on the native path and fails on the forced cross-fetch path. Both pass on Node 24.16.0 (unaffected release).

Must

  • Tests
  • Documentation (if applicable)

node-fetch@2 (via cross-fetch) throws a false ERR_STREAM_PREMATURE_CLOSE on
keep-alive responses on Node 22.23.0 and 24.17.0 (the CVE-2026-48931 http.Agent
fix, nodejs/node#63989). Node built-in fetch (undici, Node 18+) is unaffected,
so prefer it when present and fall back to cross-fetch on older runtimes.
@shuni-bot-dev

shuni-bot-dev Bot commented Jun 18, 2026

Copy link
Copy Markdown

🐕 Starting automated code review...

Analyzing changes...

@shuni-bot-dev

shuni-bot-dev Bot commented Jun 18, 2026

Copy link
Copy Markdown

🐕 Suggested Reviewers

The reviewers are selected based on recent contributions to the affected file, ensuring they are familiar with the latest changes and context. This selection covers different contributors to provide a broader review perspective with expertise directly related to the fetch polyfill.

Reviewer Reason
nirgur Recent contributor to lib/fetch-polyfill.ts, likely familiar with the fetch implementation and related bug fixes.
nmacianx Contributed to the same file, indicating recent activity and expertise in the fetch polyfill.
mattolson Contributed to the same file, bringing recent context and understanding of the code changes.
asafshen Recent contributor to lib/fetch-polyfill.ts, capable of reviewing the latest modifications and their impact.

Suggested by Shuni based on git history and PR context. Names are not @-mentioned to avoid notifying anyone — request a review from whoever fits best.

@orius123 orius123 requested a review from dorsha June 18, 2026 19:36
@orius123 orius123 enabled auto-merge (squash) June 18, 2026 19:36
@orius123 orius123 merged commit 5c85f1f into main Jun 18, 2026
28 checks passed
@orius123 orius123 deleted the fix/node-fetch-premature-close branch June 18, 2026 19:37
dorsha pushed a commit to descope/descope-js that referenced this pull request Jun 19, 2026
…ix) (#1419)

## Summary

`@descope/nextjs-sdk` pins `@descope/node-sdk` to exactly **`2.6.0`**,
which still fetches the JWKS via `cross-fetch` → **`node-fetch@2`**.
`node-fetch@2` cannot decode **Brotli (`content-encoding: br`)**
responses, so when the CDN in front of `api.descope.com` serves the keys
endpoint with `br`, the fetch dies with `ERR_STREAM_PREMATURE_CLOSE`,
`validateJwt` throws, and `authMiddleware`/`session()` reject **every
valid token** → infinite `/sign-in` loop for all users.

`@descope/node-sdk@2.8.0` already fixes this (descope/node-sdk#742 —
*"prefer native fetch to avoid node-fetch premature close"*): it uses
the runtime's native `fetch` (undici), which decodes Brotli correctly,
and only falls back to `cross-fetch` on older runtimes.

This PR bumps the pinned dependency so `nextjs-sdk` consumers actually
receive that fix.

```diff
-    "@descope/node-sdk": "2.6.0",
+    "@descope/node-sdk": "2.8.0",
```

`node-sdk@2.8.0`'s declared dependencies are identical to `2.6.0`
(`core-js-sdk 2.62.1`, `cross-fetch 4.1.0`, `jose 5.2.2`, `tslib
2.8.1`), so the lockfile change is minimal and `pnpm install
--frozen-lockfile` passes.

## Why it's hard to diagnose

The failure is CDN-edge/POP dependent: it can appear suddenly with
**no** application or SDK change (an edge simply starts serving `br`),
and it rejects even cryptographically valid `DS` cookies.

## Context

Reported in #1418 with full root-cause analysis, in-pod isolation
evidence, and a consumer-side bundler workaround. This PR is the
upstream follow-up so the workaround is no longer necessary.

Refs #1418
Refs descope/node-sdk#742

Made with [Cursor](https://cursor.com)

Co-authored-by: danpe <danpe@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants