Skip to content

Commit

Permalink
Fix: Unix OS's should properly ignore the windows zip slipped files (#…
Browse files Browse the repository at this point in the history
…179)

* Fix: Unix OS's should properly ignore the windows zip slipped files as well.

* Tests: resurrected the original zip-slip test as is as requested
  • Loading branch information
Glen-Nicol-Garmin authored Apr 14, 2024
1 parent c743527 commit 7c4604e
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 1 deletion.
4 changes: 3 additions & 1 deletion lib/extract.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ function Extract (opts) {
// to avoid zip slip (writing outside of the destination), we resolve
// the target path, and make sure it's nested in the intended
// destination, or not extract it otherwise.
var extractPath = path.join(opts.path, entry.path);
// NOTE: Need to normalize to forward slashes for UNIX OS's to properly
// ignore the zip slipped file entirely
var extractPath = path.join(opts.path, entry.path.replace(/\\/g, '/'));
if (extractPath.indexOf(opts.path) != 0) {
return cb();
}
Expand Down
63 changes: 63 additions & 0 deletions test/uncompressed.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,66 @@ test("do not extract zip slip archive", function (t) {

});
});

function testZipSlipArchive(t, slipFileName, attackPathFactory){
var archive = path.join(__dirname, '../testData/zip-slip', slipFileName);

temp.mkdir('node-zipslip-' + slipFileName, function (err, dirPath) {
if (err) {
throw err;
}
var attackPath = attackPathFactory(dirPath);
CheckForSlip(attackPath, function(slipAlreadyExists){
if(slipAlreadyExists){
t.fail('Cannot check for slip because the slipped file already exists at "' + attackPath+ '"');
t.end();
}
else{
var unzipExtractor = unzip.Extract({ path: dirPath });
unzipExtractor.on('error', function(err) {
throw err;
});
unzipExtractor.on('close', testNoSlip);

fs.createReadStream(archive).pipe(unzipExtractor);
}
})

function CheckForSlip(path, resultCallback) {
var fsCallback = function(err){ return resultCallback(!err); };
if (fs.hasOwnProperty('access')) {
var mode = fs.F_OK | (fs.constants && fs.constants.F_OK);
return fs.access(path, mode, fsCallback);
}
// node 0.10
return fs.stat(path, fsCallback);
}

function testNoSlip() {
CheckForSlip(attackPath, function(slipExists) {
if (slipExists) {
t.fail('evil file created from ' + slipFileName + ' at "' + attackPath + '"');
fs.unlinkSync(attackPath);
} else {
t.pass('no zip slip from ' + slipFileName);
}
return t.end();
})
}
});
}

test("do not extract zip slip archive(Windows)", function (t) {
var pathFactory;
if(process.platform === "win32") {
pathFactory = function(dirPath) { return '\\Temp\\evil.txt'; }
}
else{
// UNIX should treat the backslashes as escapes not directory delimiters
// will be a file with slashes in the name. Looks real weird.
pathFactory = function(dirPath) { return path.join(dirPath, '..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\Temp\\evil.txt'); }
}

testZipSlipArchive(t, 'zip-slip-win.zip', pathFactory);
});

Binary file added testData/zip-slip/zip-slip-win.zip
Binary file not shown.

0 comments on commit 7c4604e

Please sign in to comment.