Severity
Details
- CVSS score
- 7.5
- CVSS vector
- CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Overview
About vulnerability
Summary
node-tar (npm tar) contains an uncontrolled-recursion stack-exhaustion DoS in the internal mapHas helper used by filesFilter. When a consumer calls tar.t(...) or tar.x(...) with a non-empty member-selection list, node-tar installs a filter that closes over the recursive mapHas (src/list.ts:33-44). mapHas walks an entry path upward one path.dirname() call per recursion with no segment cap. A single crafted tar with a GNU-L (or PAX-x) long-path header can deliver a path of tens of thousands of /-separated segments (up to maxMetaEntrySize = 1 MiB). The recursion overflows the call stack, throwing an uncatchable RangeError that terminates the Node process on async/streaming consumers.
Root Cause
filesFilter (src/list.ts:27-51) is installed whenever a caller passes a member-selection list (src/list.ts:119-122, src/extract.ts:55-57). Its filter is invoked at src/parse.ts:253 (entry.ignore = entry.ignore || !this.filter(entry.path, entry)) inside Parser[CONSUMEHEADER] — and crucially outside the only try/catch in that method (which wraps new Header at src/parse.ts:179-183). mapHas recurses once per path segment with no depth limit. The Unpack maxDepth guard (src/unpack.ts:342, in [CHECKPATH]) only runs on the 'entry' event, which fires after CONSUMEHEADER has already invoked the filter — so the stack overflows before any depth guard executes. tar.t (list) has no maxDepth at all.
Impact
Unauthenticated, remotely-triggerable denial of service: a ~188-byte gzip (≈26 KB tar) crashes any service that lists or extracts selected members from an untrusted archive (package registries, CI artifact/cache restore, upload processors). On async (await tar.t(...)/tar.x(...)) and streaming/pipe consumers the RangeError escapes the promise as an uncaughtException and terminates the process — standard defensive try/catch around the async call does NOT prevent it. (The synchronous API is catchable; the async/stream paths — the dominant server pattern — are not.)
Proof of Concept
// Build a tar whose single entry has a GNU-L long path of ~12,000 "a/" segments (~26 KB),
// gzip it (≈188 bytes), then have a consumer list/extract with member selection:
const tar = require('tar');
await tar.t({ file: 'evil.tar.gz', gzip: true }, ['some-member']); // -> RangeError, process exit
Empirically reproduced on Node v24.18.0 against built dist/commonjs of node-tar 7.5.20: 188-byte gzip → 26,112-byte tar (12,000 segments) → uncaught RangeError: Maximum call stack size exceeded → process exit. A control run with no member-selection list (filter not installed) parses cleanly (exit 0), isolating mapHas as the sole cause.
Attack Chain
- Entry. Attacker crafts a tar with a GNU
L(or PAXx) long-path header whose body is"a/"×~12000 (~26 KB), followed by a normal file entry.
- Guard:
maxMetaEntrySizecaps the meta body at 1 MiB (src/parse.ts:241). - Bypass proof: 26 KB ≪ 1 MiB → accepted (verified: 26 KB archive parsed up to the filter).
- Trigger. Victim service calls
tar.t({file},[sel])ortar.x({file,cwd},[sel])(member selection — a documented, common API).
- Guard:
Unpack.maxDepth(default 1024) atsrc/unpack.ts:342; decompression-ratio guard. - Bypass proof:
maxDepthlives in[CHECKPATH]on the'entry'event, which fires afterCONSUMEHEADER’s filter call — the crash occurs before it (extract exits 1 with default maxDepth).tar.thas no maxDepth. Ratio is ~139× (trivial); no total-bytes cap applies to the uncompressed meta body.
- Sink.
this.filter(entry.path)→mapHasrecurses once per/segment (src/list.ts:39).
- Guard: try/catch in
CONSUMEHEADER. - Bypass proof: the only try/catch wraps
new Header(src/parse.ts:179-183); thethis.filter(...)call atsrc/parse.ts:253is outside it. TheRangeErrorpropagates out of the stream write/'data'path → uncaught exception (verified:process.on('uncaughtException')fires; asyncawait+try/catchdoes NOT intercept).
- Impact. Node process termination; a 188-byte gzip crashes any consumer that lists/extracts selected members from untrusted archives.
Bypass Evidence
mapHasrecursion is member-name-independent: the crash fires even when the requested members do not match the malicious entry path — the attacker only needs the consumer to use member selection.- Standalone
mapHasoverflows at 20k–30k segments; on the real streaming path (atopwrite → CONSUMECHUNK → CONSUMEHEADER → filter) it crashes at ≤8k segments (finder’s ~12k estimate is accurate for the reachable path). - Control (no member list → no filter) parses cleanly (exit 0), isolating
mapHas.
Affected Versions
<= 7.5.20 (npm tar). mapHas present verbatim on tag v7.5.20 (latest GitHub release and npm dist-tag latest); no segment/depth cap in src/list.ts or the CONSUMEHEADER filter path; HEAD == 7.5.20, no unreleased fix.
Suggested Fix
Rewrite mapHas iteratively (walk dirname in a while loop with a segment/visited cap), or enforce a hard path-segment limit in Header/Parser independent of maxMetaEntrySize, applied before any per-entry filter runs.
Dedup Note
Distinct from CVE-2024-28863 / GHSA-f5x3-32g6-qm9j “lack of folders depth validation” (that bounds mkdir recursion during extraction via maxDepth in Unpack[CHECKPATH] on the 'entry' event — a different sink, code path, and fix; runs after the filter and does not apply to tar.t). Also distinct from the PAX NUL/numeric-path crash advisories (improper-input-to-fs / type confusion, not recursion) and the gzip-bomb advisory (resource exhaustion on disk writes). None touch list.ts/filesFilter/mapHas or require member selection.
Reported by zx (Jace) — GitHub: @manus-use
Details
- Affected product:
- @expo/build-tools , AngularJS , Next.js , Node.js , React , adk-js , angular-create , angular-devkit-build-angular , angular-pwa , apollo-gateway , apollo-server-plugin-operation-registry , appkit , babel-preset-expo , berry , better-sqlite3 , c12 , cacache , canvas , celo-celocli , celo-connect , celo-contractkit , celo-dev-utils , celo-encrypted-backup , celo-explorer , celo-governance , celo-identity , celo-keystores , celo-phone-number-privacy-common , celo-utils , celo-wallet-base , celo-wallet-hsm , celo-wallet-hsm-azure , celo-wallet-hsm-gcp , celo-wallet-ledger , celo-wallet-local , celo-wallet-remote , celo-wallet-rpc , chain-jslib , codesmith , copy-webpack-plugin , create-medplum , create-react-app , create-storybook , create-yarn-workspaces , daytonaio-sdk , developer-tooling , duckdb-node , eas-cli , epub-iconv-segment , expo , expo-app-integrity , expo-asset , expo-auth-session , expo-background-fetch , expo-blur , expo-constants , expo-crypto , expo-dev-server , expo-dev-tools , expo-error-recovery , expo-expo-cli , expo-font , expo-image , expo-image-utils , expo-intent-launcher , expo-keep-awake , expo-linear-gradient , expo-linking , expo-mesh-gradient , expo-metro-config , expo-modules-core , expo-modules-jsi , expo-modules-test-core , expo-navigation-bar , expo-network , expo-network-addons , expo-next-adapter , expo-prebuild-config , expo-print , expo-pwa , expo-router , expo-screen-capture , expo-sharing , expo-splash-screen , expo-sqlite , expo-standard-web-crypto , expo-status-bar , expo-symbols , expo-task-manager , expo-template-bare-minimum , expo-template-blank , expo-template-blank-typescript , expo-template-default , expo-template-tabs , expo-web-browser , expo-webpack-config , expo-widgets , expo-xdl , expo-yarn-workspaces , facebook-create-react-app , fun , gatsby , gatsby-plugin-manifest , gatsby-plugin-sharp , giget , google-adk , graphql-hive-envelop , graphql-mesh , graphql-mesh-cache-cfw-kv , graphql-mesh-cache-inmemory-lru , graphql-mesh-cache-localforage , graphql-mesh-cache-redis , graphql-mesh-fusion-composition , graphql-mesh-merger-stitching , graphql-mesh-mysql , graphql-mesh-plugin-hive , graphql-mesh-plugin-http-cache , graphql-mesh-plugin-mock , graphql-mesh-transform-cache , graphql-mesh-transform-hoist-field , graphql-mesh-transform-naming-convention , graphql-mesh-transform-prefix , graphql-mesh-transform-rate-limit , graphql-mesh-transform-rename , graphql-mesh-transform-replace-field , graphql-mesh-transport-mysql , graphql-mesh-transport-sqlite , graphql-mesh-transport-thrift , graphql-mesh-tuql , graphql-yoga , grpc-node , hiero-sdk-js , ionic-cli , jest-expo , jest-expo-enzyme , jovidecroock-prefresh , lazy-cacache , lazy-node-semver-ampersand , leafygreen-ui , ledger-live , ledgerhq-coin-algorand , ledgerhq-coin-aptos , ledgerhq-coin-canton , ledgerhq-coin-celo , ledgerhq-coin-concordium , ledgerhq-coin-cosmos , ledgerhq-coin-framework , ledgerhq-coin-near , ledgerhq-coin-polkadot , ledgerhq-coin-tester , ledgerhq-concordium-core , ledgerhq-domain-service , ledgerhq-hw-app-near , ledgerhq-hw-app-tezos , ledgerhq-hw-transport , ledgerhq-hw-transport-mocker , ledgerhq-hw-transport-node-hid-noevents , ledgerhq-hw-transport-node-speculos , ledgerhq-hw-transport-web-ble , ledgerhq-hw-transport-webusb , ledgerhq-live-cli , ledgerhq-live-common , ledgerhq-live-countervalues , ledgerhq-live-currency-format , ledgerhq-live-nft , ledgerhq-live-nft-react , ledgerjs , lerna , lerna-conventional-commits , lerna-get-packed , lg-charts-colors , lg-tools-install , lg-tools-storybook-addon , libcipm , libnpm , libnpmdiff , libnpmexec , libnpmfund , libnpmorg , libnpmversion , make-fetch-happen , medplum , medplum-app , medplum-bot-layer , medplum-ccda , medplum-cdk , medplum-cli , medplum-core , medplum-definitions , medplum-dosespot-react , medplum-eslint-config , medplum-fhir-router , medplum-fhirtypes , medplum-health-gorilla-core , medplum-health-gorilla-react , medplum-hl7 , medplum-mock , medplum-react , medplum-react-hooks , microsoft-rush , microsoft-rush-lib , mikro-orm , mikro-orm-cli , mikro-orm-core , mikro-orm-entity-generator , mikro-orm-libsql , mikro-orm-mariadb , mikro-orm-migrations , mikro-orm-migrations-mongodb , mikro-orm-mssql , mikro-orm-mysql , mikro-orm-postgresql , mikro-orm-reflection , mikro-orm-seeder , mikro-orm-sqlite , minimizer-webpack-plugin , modern-js-app-tools , modern-js-babel-compiler , modern-js-babel-plugin-module-resolver , modern-js-babel-preset , modern-js-base-generator , modern-js-core , modern-js-generator-utils , modern-js-plugin-i18n , modern-js-plugin-polyfill , modern-js-prod-server , modern-js-rsbuild-plugin-esbuild , modern-js-server , modern-js-server-core , modern-js-server-utils , modern-js-tsconfig , modern-js-uni-builder , modern-js-utils , modern.js , nde , netlify-build , netlify-dev , netlify-edge-bundler , netlify-framework-info , netlify-functions-utils , netlify-headers-parser , netlify-vite-plugin , netlify-zip-it-and-ship-it , netlify/functions , nft , ng-packagr , nitro , noble , npm , npm-check-updates , npm-lifecycle , npm-package-json-loader , npm-profile , npm-registry-fetch , npm:libnpmpack , npmcli-arborist , npmcli-metavuln-calculator , nuxt , nuxt-kit , nuxt-schema , nuxt-vite-builder , nuxt-webpack-builder , oclif-plugin-plugins , omnigraph-mysql , omnigraph-thrift , opencensus-node , pacote , patch-project , pdfjs-dist , pprof , protractor , remix , remix-run-server-runtime , reown-appkit , reown-appkit-adapter-bitcoin , reown-appkit-adapter-ethers , reown-appkit-adapter-ethers5 , reown-appkit-adapter-solana , reown-appkit-adapter-wagmi , reown-appkit-common , reown-appkit-controllers , reown-appkit-core , reown-appkit-experimental , reown-appkit-pay , reown-appkit-scaffold-ui , reown-appkit-siwe , reown-appkit-siwx , reown-appkit-ui , reown-appkit-universal-connector , reown-appkit-utils , reown-appkit-wallet , reown-appkit-wallet-button , run-script , rushstack , rushstack-lockfile-explorer , rushstack-rush-amazon-s3-build-cache-plugin , rushstack-rush-azure-storage-build-cache-plugin , rushstack-rush-serve-plugin , sb , sdk-typescript , sharp , sigstore-js , sort-package-json3 , sqlite3 , storybook , storybook-addon-a11y , storybook-addon-docs , storybook-addon-links , storybook-addon-onboarding , storybook-addon-themes , storybook-addon-vitest , storybook-angular , storybook-builder-webpack5 , storybook-cli , storybook-codemod , storybook-core , storybook-core-server , storybook-core-webpack , storybook-ember , storybook-html , storybook-html-vite , storybook-nextjs , storybook-nextjs-vite , storybook-preact , storybook-preset-create-react-app , storybook-preset-react-webpack , storybook-preset-server-webpack , storybook-react , storybook-react-dom-shim , storybook-react-native-web-vite , storybook-react-vite , storybook-react-webpack5 , storybook-server , storybook-server-webpack5 , storybook-svelte , storybook-vue3 , storybook-vue3-vite , storybook-vue3-webpack5 , storybook-web-components , storybook-web-components-vite , storybook-web-components-webpack5 , swarm-js , sync-lockfile , tar , tar-pack , telemetry , temporalio-worker , tiged , tuf-js , tuql , up-require , update-versions , vercel , vercel-backends , vercel-cervel , vercel-elysia , vercel-express , vercel-fastify , vercel-h3 , vercel-hono , vercel-koa , vercel-nestjs , vercel-next , vercel-node , vercel-python , vercel-redwood , vercel-remix-builder , vercel-static-build , vinxi , wdio-browserstack-service , web-infra-dev/modern.js , web3 , web3-bzz , web3-core , web3-core-helpers , web3-core-method , web3-core-promievent , web3-core-requestmanager , web3-core-subscriptions , web3-eth , web3-eth-accounts , web3-eth-contract , web3-eth-ens , web3-eth-iban , web3-eth-personal , web3-net , web3-providers-http , web3-providers-ipc , web3-providers-ws , web3-shh , web3-utils , web3.js , webdriver-manager , webpack , webpack-cli-generators , workspaces-config , ws-pkg-list , ws-root-changelog , ws-segment , ws-yarn-workspaces , xdl , yarn-list-link , yarn-tool-changelog , yarn-tool-dotenv , yarn-tool-find-deps , yarn-tool-fix-all , yarn-tool-fix-ws-links , yarn-tool-fix-ws-pkgs-link , yarn-tool-fix-ws-versions , yarn-tool-get-pkg-bin , yarn-tool-ncu , yarn-tool-ncu-ws , yarn-tool-node-modules , yarn-tool-node-modules-is-alias , yarn-tool-node-modules-link , yarn-tool-normalize-deps-value , yarn-tool-npa-to-deps , yarn-tool-npa-to-deps-query , yarn-tool-npm-package-arg-util , yarn-tool-pack-package , yarn-tool-pkg-deps-add , yarn-tool-pkg-deps-util , yarn-tool-pkg-entry-util , yarn-tool-pkg-git-info , yarn-tool-pkg-hosted-info , yarn-tool-pkg-list-to-types , yarn-tool-pkg-name-to-types , yarn-tool-pkg-version-query , yarn-tool-resolve-package , yarn-tool-run-script-lifecycle , yarn-tool-sort-lerna-json , yarn-tool-version-recommended , yarn-tool-workspaces-project , yarn-tool-ws-changed , yarn-tool-ws-scope , yarn-tool-yarnlock , yarn-tool-yarnlock-entries , yarn-tool-yarnlock-fs , yarn-tool-yarnlock-ncu , yarn-tool-yarnlock-parse , yarn-tool-yarnlock-parse-raw , yarn-tool-yarnlock-stringify , yarn-tool-yarnlock-types , yarn-tool-yarnlock-util , yarnpkg-cli , yarnpkg-core , yarnpkg-extensions , yarnpkg-nm , yarnpkg-plugin-compat , yarnpkg-plugin-constraints , yarnpkg-plugin-dlx , yarnpkg-plugin-essentials , yarnpkg-plugin-file , yarnpkg-plugin-github , yarnpkg-plugin-interactive-tools , yarnpkg-plugin-link , yarnpkg-plugin-npm-cli , yarnpkg-plugin-pnp , yarnpkg-plugin-pnpm , yarnpkg-plugin-workspace-tools , yarnpkg-pnpify , yarnpkg-sdks , yeoman-generator , yeoman/environment
- Affected packages:
- nuxt @ 2.18.1 (+5075 more)