CVE-2026-10732
Description
The decompress package is vulnerable to Zip Slip, allowing arbitrary file writes and potential RCE via specially crafted ZIP archives.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
The decompress package is vulnerable to Zip Slip, allowing arbitrary file writes and potential RCE via specially crafted ZIP archives.
Vulnerability
The decompress package is vulnerable to an Arbitrary File Write via Archive Extraction (Zip Slip) when processing ZIP archives containing two entries with the same path. The first entry is a symlink to an arbitrary target, and the second is a regular file. The file content is written through the symlink to the target location outside the intended output directory. This bypasses previous path traversal protections and is due to the microtask processing order checking readlink for the second file before resolving the symlink for the first file. All versions of the package are affected.
Exploitation
An attacker can exploit this vulnerability by providing a specially crafted ZIP archive. This archive must contain two entries with the same path: a symlink to an arbitrary target and a regular file. When the archive is extracted, the content of the regular file will be written to the location specified by the symlink, which can be outside the intended extraction directory. This requires the attacker to be able to provide a malicious ZIP file to the application using the decompress package.
Impact
Successful exploitation allows an attacker to write arbitrary files to the host filesystem. If the overwritten file is an executable or a critical configuration file, this can lead to arbitrary code execution with the privileges of the application running the decompress package.
Mitigation
There is no fixed version available for the decompress package. The vulnerability bypasses existing path traversal protections, including preventWritingThroughSymlink [1]. A pull request suggests replacing indexOf with startsWith for path containment checks to fix a related issue [2].
AI Insight generated on Jun 5, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
2(expand)+ 1 more
- (no CPE)
- (no CPE)
Patches
1a2c6257970ecMerge 806d829d0790415555af7adbef54ef98bb04b305 into 84a8c1046946add1a6ae01c54dbebf312e4ffc85
3 files changed · +14 −2
fixtures/slip-prefix.tar.gz+0 −0 addedindex.js+2 −2 modified@@ -26,7 +26,7 @@ const safeMakeDir = (dir, realOutputPath) => { return safeMakeDir(parent, realOutputPath); }) .then(realParentPath => { - if (realParentPath.indexOf(realOutputPath) !== 0) { + if (realParentPath !== realOutputPath && !realParentPath.startsWith(realOutputPath + path.sep)) { throw (new Error('Refusing to create a directory outside the output path.')); } @@ -103,7 +103,7 @@ const extractFile = (input, output, opts) => runPlugins(input, opts).then(files .then(realOutputPath => { return fsP.realpath(path.dirname(dest)) .then(realDestinationDir => { - if (realDestinationDir.indexOf(realOutputPath) !== 0) { + if (realDestinationDir !== realOutputPath && !realDestinationDir.startsWith(realOutputPath + path.sep)) { throw (new Error('Refusing to write outside output directory: ' + realDestinationDir)); } });
test.js+12 −0 modified@@ -13,6 +13,7 @@ const rimrafP = pify(rimraf); test.serial.afterEach('ensure decompressed files and directories are cleaned up', async () => { await rimrafP(path.join(__dirname, 'directory')); await rimrafP(path.join(__dirname, 'dist')); + await rimrafP(path.join(__dirname, 'dist-evil')); await rimrafP(path.join(__dirname, 'example.txt')); await rimrafP(path.join(__dirname, 'file.txt')); await rimrafP(path.join(__dirname, 'edge_case_dots')); @@ -158,3 +159,14 @@ test.serial('throw when chained symlinks to /tmp/dist allow escape outside root await m(path.join(__dirname, 'fixtures', 'slip3.zip'), '/tmp/dist'); }, {message: /Refusing/}); }); + +test.serial('throw when symlink target shares output path as string prefix (indexOf bypass)', async t => { + // Regression test for the indexOf prefix confusion bypass. + // A symlink pointing to '../dist-evil' resolves to a sibling whose path + // starts with the output path string 'dist' — indexOf passes it, startsWith + sep does not. + fs.mkdirSync(path.join(__dirname, 'dist-evil'), {recursive: true}); + await t.throwsAsync(async () => { + await m(path.join(__dirname, 'fixtures', 'slip-prefix.tar.gz'), path.join(__dirname, 'dist')); + }, {message: /Refusing/}); + t.false(fs.existsSync(path.join(__dirname, 'dist-evil', 'pwned.txt'))); +});
Vulnerability mechanics
Root cause
"The archive extraction logic incorrectly handles symlinks when processing entries with identical paths, allowing files to be written outside the intended directory."
Attack vector
An attacker crafts a ZIP archive containing two entries with the same path. The first entry is a symbolic link to an arbitrary target, and the second is a regular file. When the archive is extracted, the file content is written through the symbolic link to the target location outside the intended output directory. This bypasses existing path traversal protections [patch_id=4888808].
Affected code
The vulnerability lies in the `safeMakeDir` and `extractFile` functions within `index.js`. Specifically, the path validation checks using `realParentPath.indexOf(realOutputPath) !== 0` and `realDestinationDir.indexOf(realOutputPath) !== 0` were insufficient to prevent path traversal when symlinks were involved [patch_id=4888808].
What the fix does
The patch modifies the path validation logic in `index.js` to use `startsWith(realOutputPath + path.sep)` instead of `indexOf(realOutputPath) !== 0`. This change ensures that symbolic links pointing to directories outside the intended output path, even if the path string is a prefix, are correctly rejected. The test suite was also updated to include a new test case for this specific bypass scenario [patch_id=4888808].
Preconditions
- inputThe attacker must provide a specially crafted ZIP archive.
Generated on Jun 5, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
3News mentions
0No linked articles in our index yet.