cross-fetch is a thin, generally trustworthy fetch polyfill with one published CVE in its history, but most projects installing it in 2025 no longer need it at all. The package exists to give you one fetch API across Node.js, browsers, and React Native — a real problem in 2018, largely a solved one now that Node ships fetch natively. This review looks at the security record of cross-fetch, what it delegates to under the hood, and how to decide between patching it and deleting it.
What cross-fetch is, mechanically
The npm cross-fetch package is not an HTTP client of its own. It is a dispatcher:
- In browsers, it re-exports the native
fetch(or thewhatwg-fetchpolyfill for ancient targets). - In Node.js, it delegates to
node-fetch's 2.x line. - In React Native, it uses the platform's built-in fetch.
That design has a direct security consequence: on the server, the security properties of cross fetch calls are mostly the security properties of node-fetch. When you audit this package, you are really auditing a two-link chain, and advisories against either link can affect you.
npm ls cross-fetch node-fetch
# └─┬ cross-fetch@4.x
# └── node-fetch@2.7.x
The one direct CVE: cookie leakage on redirect
In 2022, cross-fetch received its only direct advisory, CVE-2022-1365. When a request carrying a Cookie header hit a redirect, cross-fetch followed the Location target and replayed the cookie to the new host — including a completely different origin. Fetch example.com with a session cookie, get redirected to attacker.example, and your credential travels along.
Key facts, all from the advisory record:
- Affected: versions before 3.1.5.
- Fixed in: 3.1.5.
- Severity: moderate (CVSS 6.1).
- Class: exposure of private information to an unauthorized actor via redirect handling.
If your lockfile resolves any cross-fetch release below 3.1.5, upgrade. The 3.x and 4.x lines both contain the fix.
Inherited risk: the node-fetch 2.x line
Because the Node path delegates to node-fetch 2.x, two node-fetch advisories matter to cross-fetch users even though they carry a different package name:
- CVE-2022-0235: node-fetch forwarded
authorization,cookie, and other secure headers when redirected to a different, untrusted origin. Fixed in node-fetch 2.6.7 (and 3.1.1 on the 3.x line). Rated high. - CVE-2020-15168: the
sizeoption was not enforced after a redirect, so oversized responses never threw, enabling resource-exhaustion issues. Fixed in node-fetch 2.6.1.
Because cross-fetch declares node-fetch with a caret range, fresh installs resolve to patched 2.6.x/2.7.x releases. The risk lives in old lockfiles that pinned a vulnerable resolution years ago and were never regenerated. npm audit or a proper scanner will catch this; eyeballing package.json will not, because the manifest range looks fine. This transitive-pin problem is exactly what SCA tooling exists to catch across a whole org — a scanner like Safeguard flags the resolved version in the lockfile, not the declared range.
For a deeper look at the underlying client's history, see our node-fetch security guide.
Package health check
Health signals for cross-fetch as of this review:
- Maintenance: single primary maintainer (lquixada), slow but responsive cadence. The package is intentionally small, so low release frequency is not itself a red flag.
- Scope: tiny API surface — it re-exports fetch and nothing else. Small surface means small patch burden.
- Download base: tens of millions of weekly downloads, mostly as a transitive dependency of SDKs that wanted isomorphic HTTP.
- Advisory response: the 2022 cookie issue was patched and disclosed through the standard GitHub advisory process.
Nothing here says "abandonware," but everything says "legacy shim." The package's own reason to exist is shrinking with every Node LTS cycle.
Do you still need it?
Run this decision quickly:
- Node 18+ only? You do not need cross-fetch. Native
fetch(built on undici) is available globally without a flag. Delete the dependency and the whole node-fetch subtree leaves your SBOM. - Shipping a library that must support Node 16 and browsers? cross-fetch remains a reasonable choice — pinned at or above 3.1.5.
- React Native? The platform provides fetch; cross-fetch mostly passes through, so you can usually drop it there too.
Removing a polyfill is one of the cheapest supply chain wins available: fewer packages, fewer advisories to triage, faster installs. Every dependency you delete is a permanent reduction in audit workload, which compounds nicely when security budgets are under scrutiny.
Migration example
Swapping cross fetch usage for native fetch is usually mechanical:
// before
import fetch from 'cross-fetch';
const res = await fetch('https://api.example.com/items', {
headers: { authorization: `Bearer ${token}` },
});
// after (Node 18+): delete the import, fetch is global
const res = await fetch('https://api.example.com/items', {
headers: { authorization: `Bearer ${token}` },
});
Differences to test before merging:
- Native fetch does not support the node-fetch-specific
agentoption; connection tuning goes through undici'sdispatcher. - Timeouts are handled with
AbortSignal.timeout(ms)rather than atimeoutoption. - Error shapes differ slightly (
TypeErrorfrom undici vsFetchErrorfrom node-fetch); update your catch blocks.
Redirects and credentials: the recurring theme
It is worth noticing that the direct CVE and the inherited node-fetch CVE are the same bug class: credentials replayed across an origin boundary during redirect handling. The whole family of fetch shims hit it — as did follow-redirects, the equivalent layer under axios. When you review any HTTP client, redirect behavior with attached credentials should be the first thing you test, because it is the most common failure. A two-line integration test that redirects from your API host to a second local origin and asserts the Authorization header was dropped will catch regressions in whatever client you use.
FAQ
Is cross-fetch safe to use?
Yes, at version 3.1.5 or later. The only direct advisory (CVE-2022-1365, cookie leakage on cross-origin redirects) is fixed from 3.1.5 onward. On Node, also make sure your lockfile resolves its node-fetch dependency to 2.6.7 or later.
What is the difference between cross-fetch and node-fetch?
node-fetch is an actual HTTP client implementing the fetch API for Node.js. cross-fetch is a wrapper that picks the right fetch for your environment — node-fetch on the server, native or polyfilled fetch in browsers and React Native.
Do I need cross-fetch with Node 18?
No. Node 18 and later expose a global native fetch, so applications targeting modern Node can remove cross-fetch entirely. It is still useful for libraries that must support older Node versions and browsers from a single codebase.
How do I check which version of cross-fetch I am actually running?
Use npm ls cross-fetch to see the resolved version from your lockfile, and npm audit to check it against known advisories. The manifest range in package.json does not tell you what is installed.