diff --git a/.gitignore b/.gitignore index 118a137..cd38f37 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules test/fixtures/copy +test/fixtures/invalid diff --git a/index.js b/index.js index e4c1857..2e1ae6d 100644 --- a/index.js +++ b/index.js @@ -295,21 +295,28 @@ exports.extract = function (cwd, opts) { }, stat) } - mkdirfix(path.dirname(name), { - fs: xfs, own: own, uid: header.uid, gid: header.gid - }, function (err) { + var dir = path.dirname(name) + + validate(xfs, dir, path.join(cwd, '.'), function (err, valid) { if (err) return next(err) + if (!valid) return next(new Error(dir + ' is not a valid path')) - switch (header.type) { - case 'file': return onfile() - case 'link': return onlink() - case 'symlink': return onsymlink() - } + mkdirfix(dir, { + fs: xfs, own: own, uid: header.uid, gid: header.gid + }, function (err) { + if (err) return next(err) - if (strict) return next(new Error('unsupported type for ' + name + ' (' + header.type + ')')) + switch (header.type) { + case 'file': return onfile() + case 'link': return onlink() + case 'symlink': return onsymlink() + } - stream.resume() - next() + if (strict) return next(new Error('unsupported type for ' + name + ' (' + header.type + ')')) + + stream.resume() + next() + }) }) }) @@ -318,6 +325,15 @@ exports.extract = function (cwd, opts) { return extract } +function validate (fs, name, root, cb) { + if (name === root) return cb(null, true) + fs.lstat(name, function (err, st) { + if (err && err.code !== 'ENOENT') return cb(err) + if (err || st.isDirectory()) return validate(fs, path.join(name, '..'), root, cb) + cb(null, false) + }) +} + function mkdirfix (name, opts, cb) { mkdirp(name, {fs: opts.xfs}, function (err, made) { if (!err && made && opts.own) { diff --git a/test/fixtures/invalid.tar b/test/fixtures/invalid.tar new file mode 100644 index 0000000..a645e9c Binary files /dev/null and b/test/fixtures/invalid.tar differ diff --git a/test/index.js b/test/index.js index e9b57be..3129eb7 100644 --- a/test/index.js +++ b/test/index.js @@ -292,3 +292,21 @@ test('not finalizing the pack', function (t) { t.deepEqual(aFiles, ['hello.txt']) } }) + +test('do not extract invalid tar', function (t) { + var a = path.join(__dirname, 'fixtures', 'invalid.tar') + + var out = path.join(__dirname, 'fixtures', 'invalid') + + rimraf.sync(out) + + fs.createReadStream(a) + .pipe(tar.extract(out)) + .on('error', function (err) { + t.ok(/is not a valid path/i.test(err.message)) + fs.stat(path.join(out, '../bar'), function (err) { + t.ok(err) + t.end() + }) + }) +})