diff --git a/lib/unpack.js b/lib/unpack.js index 6034110d..726c4576 100644 --- a/lib/unpack.js +++ b/lib/unpack.js @@ -523,13 +523,13 @@ class Unpack extends Parser { // then that means we are about to delete the directory we created // previously, and it is no longer going to be a directory, and neither // is any of its children. - // If a symbolic link is encountered on Windows, all bets are off. - // There is no reasonable way to sanitize the cache in such a way - // we will be able to avoid having filesystem collisions. If this - // happens with a non-symlink entry, it'll just fail to unpack, - // but a symlink to a directory, using an 8.3 shortname, can evade - // detection and lead to arbitrary writes to anywhere on the system. - if (isWindows && entry.type === 'SymbolicLink') + // If a symbolic link is encountered, all bets are off. There is no + // reasonable way to sanitize the cache in such a way we will be able to + // avoid having filesystem collisions. If this happens with a non-symlink + // entry, it'll just fail to unpack, but a symlink to a directory, using an + // 8.3 shortname or certain unicode attacks, can evade detection and lead + // to arbitrary writes to anywhere on the system. + if (entry.type === 'SymbolicLink') dropCache(this.dirCache) else if (entry.type !== 'Directory') pruneCache(this.dirCache, entry.absolute) diff --git a/test/unpack.js b/test/unpack.js index 554f9ab5..bc1cc270 100644 --- a/test/unpack.js +++ b/test/unpack.js @@ -2719,6 +2719,10 @@ t.test('dirCache pruning unicode normalized collisions', { path: Buffer.from([0x63, 0x61, 0x66, 0x65, 0xcc, 0x81]).toString(), linkpath: 'foo', }, + { + type: 'Directory', + path: 'foo', + }, { type: 'File', path: Buffer.from([0x63, 0x61, 0x66, 0xc3, 0xa9]).toString() + '/bar', @@ -2732,7 +2736,6 @@ t.test('dirCache pruning unicode normalized collisions', { const check = (path, dirCache, t) => { path = path.replace(/\\/g, '/') t.strictSame([...dirCache.entries()], [ - [path, true], [`${path}/foo`, true], ]) t.equal(fs.readFileSync(path + '/foo/bar', 'utf8'), 'x')