CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-23950

Scharfes S, Sharp Claws: Breaking Node-Tar with Unicode Ligatures

Amit Schendel
Amit Schendel
Senior Security Researcher

Jan 21, 2026·6 min read·71 visits

Executive Summary (TL;DR)

Node-tar's locking mechanism failed to account for macOS filesystem quirks where characters like 'ß' and 'ss' are identical. This allowed attackers to bypass path reservations, leading to a race condition where a malicious symlink could be swapped in during file extraction, causing arbitrary file overwrites.

A high-severity race condition in the popular `node-tar` library allows arbitrary file overwrites on macOS systems. The vulnerability stems from a mismatch between how the library normalizes Unicode path names and how the APFS filesystem handles character ligatures (like the German 'ß'), bypassing concurrency safeguards.

The Hook: When File Systems Gaslight Developers

In the world of secure software development, the filesystem is not your friend. It is a chaotic, legacy-ridden beast that lies to you about what files exist, where they are, and what they are named. This is especially true when dealing with the unholy trinity of file extraction: symlinks, concurrency, and Unicode.

node-tar is the backbone of the Node.js ecosystem. It’s the engine that unpacks your node_modules every time you run npm install. Because installing dependencies is slow, node-tar tries to be fast. It uses a concurrency model controlled by the jobs option to extract multiple files at once. To prevent the obvious chaos of multiple threads writing to the same file, it implements a system called PathReservations. Ideally, this acts like a bouncer, ensuring that if Thread A is working on /app/config, Thread B has to wait.

But here's the catch: Logic that works perfectly on Linux (ext4) often falls apart on macOS (APFS/HFS+). While Linux is case-sensitive and literal, macOS is "helpful." It treats Hello.txt and hello.txt as the same file. Even worse, it treats certain Unicode ligatures—combined characters like the German Eszett (ß) or the ligature ff—as identical to their expanded ASCII counterparts (ss and ff). CVE-2026-23950 is the story of how that "helpfulness" allowed attackers to walk right past the bouncer.

The Flaw: A Tale of Two Normalizations

The root cause of this vulnerability is a classic Time-of-Check Time-of-Use (TOCTOU) race condition, enabled by a logic error in string normalization. The PathReservations system relies on a Map to track which file paths are currently being written to. To check if a path is busy, node-tar generates a cache key from the filename.

Prior to version 7.5.4, the library generated this key by stripping the path of relative dots (..) and applying Unicode Normalization Form D (NFD). The code looked something like this: path.normalize('NFD').toLowerCase(). The developer's assumption was that this would catch all variations of a filename. If you try to extract Foo.txt and foo.txt concurrently, they normalize to the same key, and the second job waits.

However, the NFD normalization form does not decompose the German ß into ss. In the eyes of node-tar, ß-secret.txt and ss-secret.txt were two completely different files. They generated different reservation keys (locks). Consequently, node-tar allowed operations on both files to proceed in parallel.

But the macOS kernel (XNU) disagrees. To APFS, ß and ss are the same inode. By creating a tarball with both names, an attacker could trigger two parallel threads targeting the exact same physical location on the disk, completely bypassing the library's internal locking mechanism.

The Code: shaking It Off

The fix required a fundamental change in how node-tar views strings. Simply lowercasing a string isn't enough when dealing with aggressive filesystem normalization. The patch introduces a "shake out" technique—forcing the string to expand and contract to catch these edge cases.

Here is the diff that closed the hole. Note specifically the sequence of operations:

// src/normalize-unicode.ts
 
export const normalizeUnicode = (s: string): string => {
  return s
    .normalize('NFD')
    .toLocaleLowerCase('en')
    // The magic fix: round-tripping through UpperCase forces expansion.
    // 'ß'.toLocaleUpperCase() becomes 'SS'.
    .toLocaleUpperCase('en') 
}

> [!NOTE] > Why this works: The .toLocaleUpperCase('en') method is aggressive. It knows that the uppercase version of ß is SS. By converting everything to uppercase after decomposition, the library ensures that both the ligature ß and the ASCII sequence ss resolve to the generic SS. The collision is detected, the lock is shared, and the race condition is neutralized.

The Exploit: Symlink Poisoning

To exploit this, we don't need memory corruption; we just need precise timing. The goal is Arbitrary File Overwrite. We want to trick node-tar into writing a file to a sensitive location (e.g., ~/.ssh/authorized_keys) by abusing a symlink.

Here is the attack chain:

  1. Craft the Archive: Create a tarball with two entries.

    • Entry A: A Symlink named ß pointing to ~/.ssh/.
    • Entry B: A File named ss containing the attacker's public key.
  2. The Setup: The victim runs tar.extract with jobs: 2 (or higher) on a Mac.

  3. The Race:

    • node-tar sees ß and ss as different. It grants locks for both immediately.
    • Thread 1 (Entry A) begins creating the symlink ß -> ~/.ssh/.
    • Thread 2 (Entry B) performs directory traversal checks for ss. It checks: "Is ss safe? Does the parent exist?" Since the symlink hasn't been flushed to disk yet (or the check logic ignores the parallel operation), the check passes.
  4. The Switch:

    • Thread 1 finishes. The filesystem now contains a symlink at ./ß (which is also ./ss).
    • Thread 2 proceeds to the write phase. It opens ./ss for writing.
  5. The Impact: Because APFS resolves ./ss to the symlink created by Thread 1, the write operation follows the link. The attacker's public key is written to ~/.ssh/authorized_keys (or the file inside the directory depending on exact path construction). Game over.

The Impact: Why Should We Panic?

While this vulnerability requires specific conditions (macOS, jobs > 1, extracting untrusted tarballs), the context of node-tar makes it critical. This library isn't just a utility; it is the installer for the Node.js universe.

If a package manager or build tool uses a vulnerable version of node-tar to unpack a malicious npm package (a supply chain attack vector), the attacker gains the ability to overwrite any file the user has write access to. In a CI/CD environment, this often means overwriting build scripts, injecting backdoors into the resulting artifacts, or stealing secrets by overwriting configuration files to point to external loggers.

Because the attack relies on filesystem behavior (APFS/HFS+), it is invisible to standard static analysis tools that look for buffer overflows or prototype pollution. It is a logic flaw pure and simple, and those are always the hardest to catch.

The Fix: Mitigation Strategies

The immediate fix is to upgrade node-tar to version 7.5.4. This version includes the improved Unicode normalization logic that correctly identifies ligatures as collisions.

If you cannot upgrade immediately, you must disable concurrent extraction or filter out symlinks. Since the race condition depends on two threads operating simultaneously, setting jobs: 1 effectively mitigates the issue, albeit at the cost of performance.

Alternatively, enforce strict input validation. If your application extracts tarballs from untrusted sources, use the filter option to reject SymbolicLink entries entirely until the patch is applied. Remember: trusting user input is bad, but trusting user input that interacts with the filesystem is suicidal.

Official Patches

GitHubOfficial GitHub Security Advisory

Fix Analysis (1)

Technical Appendix

CVSS Score
8.8/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:H/A:L
EPSS Probability
0.01%
Top 98% most exploited

Affected Systems

macOS (APFS filesystem)macOS (HFS+ filesystem)Node.js applications using `node-tar` <= 7.5.3

Affected Versions Detail

Product
Affected Versions
Fixed Version
node-tar
isaacs
<= 7.5.37.5.4
AttributeDetail
CWE IDCWE-367 (TOCTOU Race Condition)
Secondary CWECWE-176 (Improper Handling of Unicode Encoding)
CVSS8.8 (High)
Attack VectorNetwork (Malicious Tarball)
PlatformmacOS / Node.js
EPSS Score0.00014 (Low Probability)

MITRE ATT&CK Mapping

T1106Native API
Execution
T1059.007Command and Scripting Interpreter: JavaScript
Execution
CWE-367
Time-of-check Time-of-use (TOCTOU) Race Condition

Vulnerability Timeline

Fix committed to repository
2026-01-19
CVE-2026-23950 published
2026-01-20
GHSA Advisory released
2026-01-20

References & Sources

  • [1]Patch Commit
  • [2]NVD Entry

More Reports

•about 2 hours ago•CVE-2022-0492
7.8

CVE-2022-0492: Privilege Escalation and Container Escape via cgroups v1 release_agent

CVE-2022-0492 is a high-severity missing authorization vulnerability in the Linux kernel's Control Groups (cgroups) v1 implementation. The flaw resides within the cgroup_release_agent_write function in kernel/cgroup/cgroup-v1.c, where the kernel fails to validate if the process writing to the release_agent file possesses administrative capabilities in the initial user namespace. This allows a local attacker inside a container with root privileges (UID 0) to abuse user namespaces, mount a cgroups v1 directory, modify the release_agent parameter, and execute arbitrary commands on the host system as host root, effectively achieving a complete container escape.

Amit Schendel
Amit Schendel
4 views•7 min read
•2 days ago•GHSA-G72G-R7M4-9X4G
6.3

GHSA-G72G-R7M4-9X4G: Insufficient Session Expiration of OAuth Tokens in NocoDB

NocoDB is subject to an insufficient session expiration vulnerability where OAuth access and refresh tokens are not invalidated or revoked during security-sensitive actions such as password changes, forgot-password requests, or password resets. This allows an attacker possessing an active OAuth token to maintain unauthorized persistence.

Amit Schendel
Amit Schendel
8 views•6 min read
•2 days ago•GHSA-FGMC-2HQJ-86V4
6.9

GHSA-FGMC-2HQJ-86V4: Default Administrative Credentials in vantage6-server

A vulnerability in the vantage6 federated learning framework allows unauthenticated remote attackers to gain administrative control of the server via hardcoded default credentials (root/root) when deployed under default configurations in versions 4.2.3 and below.

Amit Schendel
Amit Schendel
8 views•5 min read
•2 days ago•GHSA-X9F6-9RVM-MMRG
6.9

GHSA-X9F6-9RVM-MMRG: Improper Access Control and Volume Mount Isolation Bypass in vantage6 Node

An improper access control vulnerability in the vantage6 node component allows concurrently running algorithm containers to read and modify sensitive input and output files of other tasks. The lack of strict workspace directory isolation exposes a significant attack surface in multi-tenant or federated environments where untrusted algorithms are executed.

Amit Schendel
Amit Schendel
3 views•4 min read
•2 days ago•CVE-2026-47760
8.7

CVE-2026-47760: Cross-Site Scripting (XSS) via SVG Namespace Sanitizer Bypass in TinyMCE

TinyMCE versions 6.8.0 through 7.0.1 contain a high-severity Cross-Site Scripting (XSS) vulnerability. The flaw exists in the custom HTML parser and sanitizer module, which incorrectly manages SVG namespace scopes when parsing nested elements. A low-privileged or unauthenticated attacker can submit a crafted HTML payload containing nested SVG structures to bypass sanitization filters, leading to arbitrary JavaScript execution in the context of the victim's browser session.

Alon Barad
Alon Barad
14 views•7 min read
•2 days ago•CVE-2026-47759
8.7

CVE-2026-47759: Stored Cross-Site Scripting (XSS) via Unsanitized data-mce-* Serialization Bypass in TinyMCE

CVE-2026-47759 is a critical stored Cross-Site Scripting (XSS) vulnerability affecting multiple active branches of the TinyMCE rich text editor. The flaw resides in the editor's handling of user-controlled, prefixed internal attributes, such as data-mce-href, data-mce-src, and data-mce-style. When processing raw HTML inputs, TinyMCE's internal validation schema neglects to inspect these custom prefixed attributes. During HTML serialization, the editor's engine extracts these unsanitized values and copies them back into standard executable attributes, overwriting any previously sanitized standard values and leading to execution of arbitrary code.

Amit Schendel
Amit Schendel
9 views•7 min read