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-101894

CVE-2026-101894: Arbitrary File Read/Write via Symbolic Link Chaining in @xhmikosr/decompress

Amit Schendel
Amit Schendel
Senior Security Researcher

Sep 30, 2026·7 min read·2 visits

Executive Summary (TL;DR)

A path traversal vulnerability in @xhmikosr/decompress allows attackers to write files outside the target directory via a crafted chain of symlink entries, bypassing lexical containment checks.

CVE-2026-101894 is a critical path traversal vulnerability in @xhmikosr/decompress before versions 10.2.2 and 11.1.4, stemming from an incomplete hardening bypass of CVE-2026-53486 where static lexical containment checks fail to detect kernel-level resolution of crafted symlink chains, allowing arbitrary local file modification and execution.

Vulnerability Overview

Node.js archive extraction libraries handle the unpacking of raw archive streams, typically ZIP or TAR files, mapping internal archive paths to filesystem structures. The default decompress(input, output) API in the @xhmikosr/decompress library and its unmaintained upstream counterpart decompress serves as the primary interface for this behavior. This component exposes a large attack surface when consuming untrusted compressed archives, particularly in applications processing automated uploads, third-party integrations, or build-system artifacts.

The vulnerability, tracked as CVE-2026-101894, belongs to the Improper Limitation of a Pathname to a Restricted Directory (CWE-22) and Improper Link Resolution Before File Access (CWE-59) classes. It represents a direct bypass of the security mechanisms introduced to resolve CVE-2026-53486. The earlier fix attempted to validate that target paths did not escape the output directory by implementing static string checks on the path components.

By constructing a malicious archive with nested, self-referential symbolic link chains, attackers can subvert these static checks. At runtime, the operating system kernel resolves the path physically rather than lexically, resulting in file creation or modification outside the designated target folder. This execution behavior can lead to local file disclosure, parameter overwrite, or arbitrary remote code execution if system configuration or startup files are altered.

Root Cause Analysis

The root cause of CVE-2026-101894 is the library's reliance on static lexical validation instead of physical filesystem validation before creating files. Static path resolution methods evaluate strings without querying the physical state of the underlying filesystem. When analyzing symbolic links, the physical target of the symlink dictates how subsequent relative path segments (specifically parent directory navigations via ..) are processed by the operating system kernel.

If an archive contains a symbolic link entry a that points to the current directory ., the physical directory structure is unaffected at the lexical layer. A subsequent entry b pointing to a/../secret.txt appears to the static path-resolution mechanism as secret.txt after collapsing the relative segments statically because the parent of .. is evaluated as a. Lexically, the path secret.txt is judged to reside within the designated extraction boundary, and the security boundary check evaluates to a pass status.

When the extraction engine writes these files, the operating system processes the actual creation. The kernel accesses the directory entry a, recognizes it physically points to ., and stays within the extraction folder. However, when parsing the next segment .., the kernel navigates to the physical parent of the current folder, effectively escaping the extraction directory entirely. The terminal segment secret.txt is then written to this higher-level directory, bypassing all static directory boundary enforcement.

Code Analysis

The previous, vulnerable validation logic attempted to enforce directory containment by inspecting paths prior to disk writes. The function ensureLinkTargetInsideOutput performed simple string operations and lexical resolves, which failed to evaluate runtime filesystem layouts. Below is the conceptual representation of the vulnerable check alongside the patched approach which implements physical resolution.

The updated implementation introduces two main functions: resolveMaybeMissing and assertSymlinkResolvesInside. The resolveMaybeMissing function recursively climbs the directory structure of a target path, resolving the longest existing physical prefix using the realpath API. It then appends any non-existent trailing directories to ensure that physical paths are computed accurately even if files do not yet exist on disk.

To inspect the exact patch changes, refer to the following code snippet showing the replacement logic that prevents the lexical containment bypass:

// Vulnerable Lexical Path Containment (Concept)
// const safe = path.resolve(outputPath, linkname).startsWith(outputPath);
 
// Patched Physical Resolution Mechanism
const resolveMaybeMissing = async target => {
	let existing = target;
	const tail = [];
 
	for (;;) {
		try {
			// Resolve the longest physically existing path using the filesystem realpath
			return path.join(await realpath(existing), ...tail.toReversed());
		} catch {
			const parent = path.dirname(existing);
			if (parent === existing) {
				return target;
			}
 
			tail.push(path.basename(existing));
			existing = parent;
		}
	}
};
 
const assertSymlinkResolvesInside = async (dest, linkname, realOutputPath) => {
	// Evaluate the raw link target dynamically without collapsing relative segments lexically
	const rawTarget = path.isAbsolute(linkname) ? linkname : path.dirname(dest) + path.sep + linkname;
	const resolved = await resolveMaybeMissing(rawTarget);
 
	if (!isInsideOutput(resolved, realOutputPath)) {
		await unlink(dest).catch(() => null);
		throw new Error(`Refusing to keep a symlink that escapes the output directory: ${dest}`);
	}
};

In addition to the physical path check, the patch introduces multi-phase extraction where symlinks are validated post-extraction, and files are opened with the O_NOFOLLOW flag to prevent writing through pre-existing symlinks. The O_NOFOLLOW flag forces the operating system to reject writes that would follow symbolic links, eliminating Time-of-Check to Time-of-Use (TOCTOU) race conditions.

Exploit Methodology and PoC

An exploitation chain targeting CVE-2026-101894 requires an attacker to construct a ZIP or TAR archive containing at least two distinct entries. The first entry must establish a symbolic link pointing to a directory within the structure, typically using the relative path self-reference .. The second entry is another symbolic link that references the first link followed by a parent traversal string pointing to a sensitive file target.

When the target Node.js application invokes the decompress API on this archive, the vulnerable library processes the directory entry. It fails to detect that the second symbolic link resolves physically to an external file. Once the symbolic links are written to disk, subsequent files or directory writes targeting the second symlink name will overwrite files outside the root extraction folder.

The process flow below illustrates the evaluation sequence of the symbolic link chain during extraction:

No specialized privileges or complex configurations are required to trigger the vulnerability. The attack can be executed remotely if the application allows users to upload custom compressed archives and extracts them to a server-side directory. If the application runs as a privileged user such as root, the write vector can target system configuration directories.

Impact Assessment

The impact of CVE-2026-101894 is categorized as critical, represented by a CVSS v3.1 score of 9.1. An attacker who successfully exploits this vulnerability can read or write arbitrary files on the host filesystem with the privileges of the Node.js process. If the application runs with high administrative access, the entire operating system environment can be compromised.

In web application deployments, arbitrary file write access often leads directly to remote code execution. Attackers can overwrite node dependency files within the node_modules directory, inject malicious scripts into startup handlers, or drop configuration files like .bashrc or systemd service configurations. When the server restarts or the affected node process executes the modified code paths, the attacker gains shell access.

While the EPSS score of 0.00814 indicates a low current probability of widespread exploitation, this score does not reflect the severity of a targeted attack. Applications operating in multitenant or shared environments that process file uploads are at elevated risk. This threat vector requires immediate remediation to prevent lateral movement and privilege escalation inside corporate infrastructure.

Remediation and Mitigation

Complete remediation of this vulnerability requires upgrading all instances of the @xhmikosr/decompress package. The developer has published official security updates addressing this vulnerability in versions 10.2.2 and 11.1.4. System administrators must identify any transitive dependencies pulling in vulnerable versions of the library.

If the legacy, unmaintained decompress package is in use within the codebase, it must be replaced. The legacy decompress library remains unpatched through its final version 4.2.1 and should be swapped for the actively maintained @xhmikosr/decompress fork. No configuration flags can secure the unmaintained package against this flaw.

Temporary mitigation strategies involve limiting the execution environment of the Node.js runtime. Deploying the application in an isolated Docker container with a non-root user and mounting extraction directories as restricted, non-executable partitions reduces the impact of directory traversal. Additionally, preprocessing incoming archives to filter out symlinks before invoking the extraction library provides an effective defense-in-depth layer.

Fix Analysis (4)

Technical Appendix

CVSS Score
9.1/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N
EPSS Probability
0.81%
Top 45% most exploited

Affected Systems

@xhmikosr/decompressdecompress

Affected Versions Detail

Product
Affected Versions
Fixed Version
@xhmikosr/decompress
@xhmikosr
< 10.2.210.2.2
@xhmikosr/decompress
@xhmikosr
< 11.1.411.1.4
decompress
kevva
<= 4.2.1None
AttributeDetail
CWE IDCWE-22
Attack VectorNetwork
CVSS Score9.1
EPSS Score0.00814
Exploit StatusPoC
KEV StatusNot Listed

MITRE ATT&CK Mapping

T1083File and Directory Discovery
Discovery
T1005Data from Local System
Collection
T1546Event Triggered Execution
Persistence
T1059Command and Scripting Interpreter
Execution
CWE-22
Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')

The software uses external input to construct a pathname that is intended to identify a file or directory that is located within a restricted directory, but the software does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location outside of the restricted directory.

Known Exploits & Detection

GitHubPublic PoC GitHub Repository
External AnalysisExternal Exploit Analysis Article

Vulnerability Timeline

Original repository improvements regarding line endings executed
2026-06-13
Base dependencies updated for decompression engines
2026-06-18
Path validation hardening implemented to protect against NUL byte and Windows-specific patterns
2026-06-26
Security researchers discover bypass vector. Patches committed to codebase
2026-08-02
Security updates officially released as versions 10.2.2 and 11.1.4
2026-08-05
Vulnerability formally disclosed and published to the National Vulnerability Database (NVD)
2026-09-28

References & Sources

  • [1]Official Security Advisory
  • [2]NVD Vulnerability Detail
  • [3]CVE.org Authority Record
  • [4]Release Version 10.2.2
  • [5]Release Version 11.1.4

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•about 2 hours ago•CVE-2026-86818
4.8

CVE-2026-86818: Mailto Header Injection via Percent-Encoded Field-Name Desynchronization in fast-uri

A security-critical desynchronization vulnerability exists in fast-uri versions 4.1.3 and 4.1.4. Due to incorrect order-of-operations, the mailto scheme parser validates raw percent-encoded parameter keys instead of normalized keys, but subsequently decodes and writes them into a generic headers object. When the parsed URI is serialized, these keys are re-emitted literally, allowing attackers to bypass validation boundaries and smuggle unauthorized recipients, subjects, or body parameters in downstream mailing applications.

Amit Schendel
Amit Schendel
5 views•6 min read
•about 3 hours ago•CVE-2026-86472
4.8

CVE-2026-86472: Hostname Canonicalization Bypass in fast-uri via Scheme-Relative URLs

CVE-2026-86472 is a validation bypass vulnerability in fast-uri (a high-performance RFC 3986 URI toolbox heavily used by popular Node.js frameworks like Fastify and validation libraries like AJV). The vulnerability stems from improper handling of case sensitivity (CWE-178) due to an incorrect order of operations during hostname canonicalization in scheme-relative URLs. An attacker can leverage percent-encoded uppercase characters within scheme-relative URLs to bypass domain blocklists/allowlists in downstream applications. Because hostname resolution in DNS and HTTP is case-insensitive, the bypassed host representation still routes to the target destination, resulting in potential Server-Side Request Forgery (SSRF) or security control bypasses.

Amit Schendel
Amit Schendel
3 views•4 min read
•about 4 hours ago•CVE-2026-102281
7.5

CVE-2026-102281: Denial of Service via Uncaught Exception in @nestjs/microservices

An unauthenticated remote attacker can crash NestJS microservices utilizing TCP or RabbitMQ transport layers. The vulnerability exists due to recursive serialization of deeply nested message patterns using JSON.stringify, leading to a RangeError and process termination.

Amit Schendel
Amit Schendel
6 views•6 min read
•about 5 hours ago•CVE-2026-18149
5.9

CVE-2026-18149: Unresolved Response Body Hang in Undici RetryHandler

A resource management vulnerability in the Undici HTTP client (CWE-772) occurs when the retry interceptor receives a partial body payload followed by a non-retryable response error on a subsequent connection attempt, resulting in orphaned streams and potential Denial of Service (DoS).

Alon Barad
Alon Barad
5 views•8 min read
•about 6 hours ago•CVE-2026-102274
5.9

CVE-2026-102274: Denial of Service via Unhandled Exception in PyJWT JWK Set Parser

A vulnerability in PyJWT's JWK Set parsing logic allows a malformed RSA key to trigger an unhandled ValueError, leading to an application-wide or request-level Denial of Service.

Alon Barad
Alon Barad
5 views•6 min read
•about 7 hours ago•GHSA-8VVX-RFF5-P5RQ
5.9

GHSA-8vvx-rff5-p5rq: Stack Exhaustion Denial of Service via Nested Recipient Arrays in Nodemailer

An uncontrolled recursion vulnerability exists in Nodemailer versions up to and including 10.0.1. When parsing recipient email addresses, recursively nested arrays bypass the parser's depth limit, resulting in V8 call stack exhaustion and immediate synchronous process termination.

Alon Barad
Alon Barad
3 views•7 min read