diff --git a/workspaces/libnpmpack/lib/index.js b/workspaces/libnpmpack/lib/index.js index df6d35cb172c6..6c8ee3fd6334d 100644 --- a/workspaces/libnpmpack/lib/index.js +++ b/workspaces/libnpmpack/lib/index.js @@ -37,7 +37,7 @@ async function pack (spec = 'file:.', opts = {}) { // check for explicit `false` so the default behavior is to skip writing to disk if (opts.dryRun === false) { const filename = `${manifest.name}-${manifest.version}.tgz` - .replace(/^@/, '').replace(/\//, '-') + .replace(/^@/, '').replace(/[/\\]/g, '-') const destination = path.resolve(opts.packDestination, filename) await writeFile(destination, tarball) } diff --git a/workspaces/libnpmpack/test/index.js b/workspaces/libnpmpack/test/index.js index 62d5af1a80d2c..c3c7ca76d4113 100644 --- a/workspaces/libnpmpack/test/index.js +++ b/workspaces/libnpmpack/test/index.js @@ -36,6 +36,29 @@ t.test('packs from local directory', async t => { }) }) +t.test('flattens path separators in name so tarball stays in packDestination', async t => { + const testDir = t.testdir({ + src: { + 'package.json': JSON.stringify({ + name: 'x/../../../../../../escaped', + version: '1.0.0', + }, null, 2), + }, + dest: {}, + }) + + const dest = path.join(testDir, 'dest') + await pack(`file:${path.join(testDir, 'src')}`, { + dryRun: false, + packDestination: dest, + silent: true, + }) + + const written = fs.readdirSync(dest) + t.same(written, ['x-..-..-..-..-..-..-escaped-1.0.0.tgz'], 'separators flattened to a single filename') + t.notOk(fs.existsSync(path.join(testDir, 'escaped-1.0.0.tgz')), 'nothing escaped the destination') +}) + t.test('writes tarball to file when dryRun === false', async t => { const testDir = t.testdir({ 'package.json': JSON.stringify({