Skip to content
This repository was archived by the owner on Jan 15, 2025. It is now read-only.

Commit 2712c11

Browse files
committed
validate parent paths
1 parent e074d9c commit 2712c11

File tree

4 files changed

+46
-11
lines changed

4 files changed

+46
-11
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
node_modules
22
test/fixtures/copy
3+
test/fixtures/invalid

index.js

+27-11
Original file line numberDiff line numberDiff line change
@@ -295,21 +295,28 @@ exports.extract = function (cwd, opts) {
295295
}, stat)
296296
}
297297

298-
mkdirfix(path.dirname(name), {
299-
fs: xfs, own: own, uid: header.uid, gid: header.gid
300-
}, function (err) {
298+
var dir = path.dirname(name)
299+
300+
validate(xfs, dir, path.join(cwd, '.'), function (err, valid) {
301301
if (err) return next(err)
302+
if (!valid) return next(new Error(dir + ' is not a valid path'))
302303

303-
switch (header.type) {
304-
case 'file': return onfile()
305-
case 'link': return onlink()
306-
case 'symlink': return onsymlink()
307-
}
304+
mkdirfix(dir, {
305+
fs: xfs, own: own, uid: header.uid, gid: header.gid
306+
}, function (err) {
307+
if (err) return next(err)
308308

309-
if (strict) return next(new Error('unsupported type for ' + name + ' (' + header.type + ')'))
309+
switch (header.type) {
310+
case 'file': return onfile()
311+
case 'link': return onlink()
312+
case 'symlink': return onsymlink()
313+
}
310314

311-
stream.resume()
312-
next()
315+
if (strict) return next(new Error('unsupported type for ' + name + ' (' + header.type + ')'))
316+
317+
stream.resume()
318+
next()
319+
})
313320
})
314321
})
315322

@@ -318,6 +325,15 @@ exports.extract = function (cwd, opts) {
318325
return extract
319326
}
320327

328+
function validate (fs, name, root, cb) {
329+
if (name === root) return cb(null, true)
330+
fs.lstat(name, function (err, st) {
331+
if (err && err.code !== 'ENOENT') return cb(err)
332+
if (err || st.isDirectory()) return validate(fs, path.join(name, '..'), root, cb)
333+
cb(null, false)
334+
})
335+
}
336+
321337
function mkdirfix (name, opts, cb) {
322338
mkdirp(name, {fs: opts.xfs}, function (err, made) {
323339
if (!err && made && opts.own) {

test/fixtures/invalid.tar

2.5 KB
Binary file not shown.

test/index.js

+18
Original file line numberDiff line numberDiff line change
@@ -292,3 +292,21 @@ test('not finalizing the pack', function (t) {
292292
t.deepEqual(aFiles, ['hello.txt'])
293293
}
294294
})
295+
296+
test('do not extract invalid tar', function (t) {
297+
var a = path.join(__dirname, 'fixtures', 'invalid.tar')
298+
299+
var out = path.join(__dirname, 'fixtures', 'invalid')
300+
301+
rimraf.sync(out)
302+
303+
fs.createReadStream(a)
304+
.pipe(tar.extract(out))
305+
.on('error', function (err) {
306+
t.ok(/is not a valid path/i.test(err.message))
307+
fs.stat(path.join(out, '../bar'), function (err) {
308+
t.ok(err)
309+
t.end()
310+
})
311+
})
312+
})

0 commit comments

Comments
 (0)