Vulnerabilities in pkg:npm/tar

PACKAGE
Advisory Identifier: GHSA-r292-9mhp-454m
Advisory Summary

CVE-2026-73566 is a HIGH (CVSS 7.5) denial of service vulnerability (CWE-400: Uncontrolled Resource Consumption) affecting node-tar libraries in the npm ecosystem. The issue involves uncontrolled recursion in maphas/filesfilter allows uncatchable stack-overflow dos via crafted long-path tar with member selection. Remediation is available by upgrading affected packages to version 7.5.21.

21 Known Advisory Record(s)
Package Vulnerability Intelligence

pkg:npm/tar

21 Known Advisory Record(s)

Vulnerability advisories affecting package pkg:npm/tar. Select an advisory below to view technical details or fixes.

Advisory ID CVE / NVD Severity Summary
GHSA-r292-9mhp-454m CVE-2026-73566 HIGH node-tar: Uncontrolled recursion in mapHas/filesFilter allows uncatchable stack-overflow DoS via crafted long-path tar with member selection
GHSA-w8wr-v893-vjvp CVE-2026-59871 MODERATE node-tar: Process crash via PAX numeric path type confusion
GHSA-23hp-3jrh-7fpw CVE-2026-59873 CRITICAL node-tar: Decompression/parse DoS via unlimited input
GHSA-8x88-c5mf-7j5w CVE-2026-59874 HIGH node-tar: Negative tar entry size causes infinite loop in archive replace
GHSA-gvwx-54wh-qm9j CVE-2026-59875 MODERATE node-tar: Uncaught Exception DoS via NUL byte in PAX path/linkpath records
GHSA-vmf3-w455-68vh CVE-2026-53655 MODERATE node-tar applies PAX size override to intermediary GNU long-name/long-link headers, causing tar parser interpretation differential (file smuggling)
GHSA-r6q2-hw4h-h46w CVE-2026-23950 HIGH Race Condition in node-tar Path Reservations via Unicode Ligature Collisions on macOS APFS
GHSA-9ppj-qmqm-q256 CVE-2026-31802 HIGH node-tar Symlink Path Traversal via Drive-Relative Linkpath
GHSA-qffp-2rhf-9h96 CVE-2026-29786 HIGH tar has Hardlink Path Traversal via Drive-Relative Linkpath
GHSA-83g3-92jg-28cx CVE-2026-26960 HIGH Arbitrary File Read/Write via Hardlink Target Escape Through Symlink Chain in node-tar Extraction
GHSA-8qq5-rm4j-mr97 CVE-2026-23745 HIGH node-tar is Vulnerable to Arbitrary File Overwrite and Symlink Poisoning via Insufficient Path Sanitization
GHSA-34x7-hfp2-rc4v CVE-2026-24842 HIGH node-tar Vulnerable to Arbitrary File Creation/Overwrite via Hardlink Path Traversal
GHSA-29xp-372q-xqph CVE-2025-64118 MODERATE node-tar has a race condition leading to uninitialized memory exposure
GHSA-f5x3-32g6-xq36 CVE-2024-28863 MODERATE Denial of service while parsing a tar file due to lack of folders count validation
GHSA-j44m-qm6p-hp7m CVE-2018-20834 HIGH Arbitrary File Overwrite in tar
GHSA-r628-mhmh-qjhw CVE-2021-32803 HIGH Arbitrary File Creation/Overwrite via insufficient symlink protection due to directory cache poisoning
GHSA-gfjr-3jmm-4g9v CVE-2015-8860 HIGH Symlink Arbitrary File Overwrite in tar
GHSA-5955-9wpr-37jh CVE-2021-37713 HIGH Arbitrary File Creation/Overwrite on Windows via insufficient relative path sanitization
GHSA-qq89-hq3f-393p CVE-2021-37712 HIGH Arbitrary File Creation/Overwrite via insufficient symlink protection due to directory cache poisoning using symbolic links
GHSA-9r2w-394v-53qc CVE-2021-37701 HIGH Arbitrary File Creation/Overwrite via insufficient symlink protection due to directory cache poisoning using symbolic links
GHSA-3jfq-g458-7qm9 CVE-2021-32804 HIGH Arbitrary File Creation/Overwrite due to insufficient absolute path sanitization

CVE-2026-73566 at a Glance

CVE Identifier CVE-2026-73566
GHSA Identifier GHSA-r292-9mhp-454m
Severity HIGH
CVSS v3.1 Base Score 7.5
CWE Classification CWE-400: Uncontrolled Resource Consumption
Affected Product node-tar
Package Ecosystem npm
Published Date
Last Updated

Security Impact

CVSS: 7.5

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H).

Attack Vector Network (AV:N)
Attack Complexity Low (AC:L)
Privileges Required None (PR:N)
User Interaction None (UI:N)
Scope Unchanged (S:U)
Confidentiality None (C:N)
Integrity None (I:N)
Availability High (A:H)

How to Fix CVE-2026-73566

To remediate this vulnerability, upgrade all affected node-tar dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

tar fixed: 7.5.21
npm install tar@7.5.21
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

npm ls tar

How to Check if You Are Affected

To determine whether your Node.js application is affected by CVE-2026-73566, inspect your project dependencies using npm:

npm ls tar

Analyze the terminal output to locate any version of node-tar in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 7.5.21), your application is affected.

Note: The npm ls tar command inspects dependencies declared in your package.json and lockfile; it does not perform automated runtime dynamic scanning.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-400: Uncontrolled Resource Consumption, where the product does not properly control the allocation and maintenance of a limited resource. In node-tar, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

## 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 ```js // 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 1. **Entry.** Attacker crafts a tar with a GNU `L` (or PAX `x`) long-path header whose body is `"a/"`×~12000 (~26 KB), followed by a normal file entry. - **Guard:** `maxMetaEntrySize` caps 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). 2. **Trigger.** Victim service calls `tar.t({file},[sel])` or `tar.x({file,cwd},[sel])` (member selection — a documented, common API). - **Guard:** `Unpack.maxDepth` (default 1024) at `src/unpack.ts:342`; decompression-ratio guard. - **Bypass proof:** `maxDepth` lives in `[CHECKPATH]` on the `'entry'` event, which fires *after* `CONSUMEHEADER`'s filter call — the crash occurs before it (extract exits 1 with default maxDepth). `tar.t` has no maxDepth. Ratio is ~139× (trivial); no total-bytes cap applies to the uncompressed meta body. 3. **Sink.** `this.filter(entry.path)` → `mapHas` recurses 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`); the `this.filter(...)` call at `src/parse.ts:253` is outside it. The `RangeError` propagates out of the stream write/`'data'` path → uncaught exception (verified: `process.on('uncaughtException')` fires; async `await`+`try/catch` does NOT intercept). 4. **Impact.** Node process termination; a 188-byte gzip crashes any consumer that lists/extracts selected members from untrusted archives. ## Bypass Evidence - `mapHas` recursion 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 `mapHas` overflows at 20k–30k segments; on the real streaming path (atop `write → 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

CVE-2026-73566 Affected node-tar Versions

1 component(s)
Fixed Versions:
7.5.21
Product / Package Ecosystem Affected Versions Fixed Version
tar
npm
< 7.5.21
7.5.21

References

Frequently Asked Questions

What is CVE-2026-73566?
CVE-2026-73566 is a security vulnerability in node-tar involving Uncontrolled recursion in mapHas/filesFilter allows uncatchable stack-overflow DoS via crafted long-path tar with member selection under CWE-400: Uncontrolled Resource Consumption.
Which node-tar versions are affected?
Affected versions include releases prior to 7.5.21 across affected packages: tar.
What version fixes CVE-2026-73566?
Upgrading to 7.5.21 (or the latest patched release for your respective branch) resolves the vulnerability.
Is tar affected?
Yes, tar is affected in releases prior to 7.5.21. Upgrade your dependency to 7.5.21 or later.
What is the CVSS score of CVE-2026-73566?
CVE-2026-73566 has a CVSS v3.1 base score of 7.5 (HIGH) with vector string CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H.
What CWE is associated with CVE-2026-73566?
CVE-2026-73566 is classified under CWE-400: Uncontrolled Resource Consumption (The product does not properly control the allocation and maintenance of a limited resource.).
How can I check npm dependencies for CVE-2026-73566?
Run the dependency tree command: 'npm ls tar'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-r292-9mhp-454m",
  "modified" : "2026-08-21T19:08:22Z",
  "published" : "2026-07-24T16:26:16Z",
  "aliases" : [ "CVE-2026-73566" ],
  "summary" : "node-tar: Uncontrolled recursion in mapHas/filesFilter allows uncatchable stack-overflow DoS via crafted long-path tar with member selection",
  "details" : "## Summary\n`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.\n\n## Root Cause\n`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.\n\n## Impact\nUnauthenticated, 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.)\n\n## Proof of Concept\n```js\n// Build a tar whose single entry has a GNU-L long path of ~12,000 \"a/\" segments (~26 KB),\n// gzip it (≈188 bytes), then have a consumer list/extract with member selection:\nconst tar = require('tar');\nawait tar.t({ file: 'evil.tar.gz', gzip: true }, ['some-member']); // -> RangeError, process exit\n```\nEmpirically 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.\n\n## Attack Chain\n1. **Entry.** Attacker crafts a tar with a GNU `L` (or PAX `x`) long-path header whose body is `\"a/\"`×~12000 (~26 KB), followed by a normal file entry.\n   - **Guard:** `maxMetaEntrySize` caps the meta body at 1 MiB (`src/parse.ts:241`).\n   - **Bypass proof:** 26 KB ≪ 1 MiB → accepted (verified: 26 KB archive parsed up to the filter).\n2. **Trigger.** Victim service calls `tar.t({file},[sel])` or `tar.x({file,cwd},[sel])` (member selection — a documented, common API).\n   - **Guard:** `Unpack.maxDepth` (default 1024) at `src/unpack.ts:342`; decompression-ratio guard.\n   - **Bypass proof:** `maxDepth` lives in `[CHECKPATH]` on the `'entry'` event, which fires *after* `CONSUMEHEADER`'s filter call — the crash occurs before it (extract exits 1 with default maxDepth). `tar.t` has no maxDepth. Ratio is ~139× (trivial); no total-bytes cap applies to the uncompressed meta body.\n3. **Sink.** `this.filter(entry.path)` → `mapHas` recurses once per `/` segment (`src/list.ts:39`).\n   - **Guard:** try/catch in `CONSUMEHEADER`.\n   - **Bypass proof:** the only try/catch wraps `new Header` (`src/parse.ts:179-183`); the `this.filter(...)` call at `src/parse.ts:253` is outside it. The `RangeError` propagates out of the stream write/`'data'` path → uncaught exception (verified: `process.on('uncaughtException')` fires; async `await`+`try/catch` does NOT intercept).\n4. **Impact.** Node process termination; a 188-byte gzip crashes any consumer that lists/extracts selected members from untrusted archives.\n\n## Bypass Evidence\n- `mapHas` recursion 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.\n- Standalone `mapHas` overflows at 20k–30k segments; on the real streaming path (atop `write → CONSUMECHUNK → CONSUMEHEADER → filter`) it crashes at ≤8k segments (finder's ~12k estimate is accurate for the reachable path).\n- Control (no member list → no filter) parses cleanly (exit 0), isolating `mapHas`.\n\n## Affected Versions\n`<= 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.\n\n## Suggested Fix\nRewrite `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.\n\n## Dedup Note\nDistinct 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.\n\n---\nReported by **zx (Jace)** — GitHub: @manus-use",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "npm",
      "name" : "tar"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "7.5.21"
      } ]
    } ],
    "database_specific" : {
      "last_known_affected_version_range" : "<= 7.5.20"
    }
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/isaacs/node-tar/security/advisories/GHSA-r292-9mhp-454m"
  }, {
    "type" : "ADVISORY",
    "url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-73566"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/isaacs/node-tar/commit/631ae59121bf8fc8a22bbae35f074cb9b789cd4a"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/isaacs/node-tar"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/isaacs/node-tar/releases/tag/v7.5.21"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-400", "CWE-674" ],
    "severity" : "HIGH",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-07-24T16:26:16Z",
    "nvd_published_at" : "2026-08-13T18:18:19Z"
  }
}