GitHub Security Advisory: GHSA-4c3q-x735-j3r5
Package: compressing (NPM)
Severity: HIGH (CVSS 8.4)
CWE: CWE-59: Improper Link Resolution Before File Access ('Link Following')
Vulnerable versions: <= 1.10.4
Patched in: 1.10.5

Summary: Complete Bypass of CVE-2026-24884 Patch via Git-Delivered Symlink Poisoning in compressing

Details:
**1. Executive Summary**
This report documents a critical security research finding in the `compressing` npm package (specifically tested on the latest **v2.1.0**). The core vulnerability is a **Partial Fix Bypass** of **CVE-2026-24884**.

The current patch relies on a purely logical string validation within the `isPathWithinParent` utility. This check verifies if a resolved path string starts with the destination directory string but fails to account for the **actual filesystem state**. By exploiting this "Logical vs. Physical" divergence, we successfully bypassed the security check using a Directory Poisoning technique (pre-existing symbolic links).

**Key Findings:**

* **Vulnerable Component:** `lib/utils.js` -> `isPathWithinParent()`
* **Flaw Type:** Incomplete validation (lack of recursive `lstat` checks).
* **Primary Attack Vector:** **Supply Chain via Git Clone** The attack requires zero victim interaction beyond standard developer workflow (`git clone` + `node app.js`). Git natively preserves symlinks during clone, automatically deploying the malicious symlink to victim's machine without any additional attacker access.
* **Result:** Successfully achieved arbitrary file writes outside the intended extraction root on the latest library version.

**2. Deep-Dive: Technical Root Cause Analysis**
The vulnerability exists because of a fundamental disconnect between how the library **validates** a path and how the Operating System **executes** a write to that path.

* **1. Logical Abstraction (The "String" World)**
The developer uses `path.resolve(childPath)` to sanitize input. In Node.js, `path.resolve` is a literal string manipulator. It calculates an absolute path by processing `..` and `.` segments relative to each other.

* **The Limitation:** `path.resolve` does **NOT** look at the disk. It does not know if a folder named `config` is a real folder or a symbolic link.
* **The Result:** If the extraction target is `/app/out` and the entry is c`onfig/passwd`, `path.resolve` returns `/app/out/config/passwd`. Since this string starts with `/app/out/`, the security check returns **TRUE**.

* **2. Physical Reality (The "Filesystem" World)**
When the library proceeds to write the file using `fs.writeFile('/app/out/config/passwd', data)`, the execution is handed over to the Operating System's filesystem kernel.

* **The Redirection:** If the attacker has pre-created a symbolic link on the disk at `/app/out/config` pointing to `/etc`, the OS kernel sees the write request and follows the link.
* **The Divergence:** The OS resolves the path to `/etc/passwd`. The "Security Guard" (the library) thought it was writing to a local config folder, but the "Executioner" (the OS) followed the link into a sensitive system area.

* **3. Visual Logic Flow**
<img width="6582" height="3095" alt="Malicious Archive Exploit-2026-04-12-135626" src="https://github.com/user-attachments/assets/7c8235c3-f717-4296-b8e7-d6d498285fb2" />

* **4. Comparison with Industry Stand