Skip to content

Commit

Permalink
Prevent directories creation outside output path
Browse files Browse the repository at this point in the history
  • Loading branch information
trptcolin committed Feb 27, 2020
1 parent 432db78 commit 8850e7e
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 4 deletions.
Binary file added fixtures/slipping_directory.tar.gz
Binary file not shown.
22 changes: 20 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,21 @@ const runPlugins = (input, opts) => {
return Promise.all(opts.plugins.map(x => x(input, opts))).then(files => files.reduce((a, b) => a.concat(b)));
};

const safeMakeDir = (dir, realOutputPath) => {
return fsP.realpath(dir)
.catch(_ => {
const parent = path.dirname(dir);
return safeMakeDir(parent, realOutputPath);
})
.then(realParentPath => {
if (realParentPath.indexOf(realOutputPath) !== 0) {
throw (new Error('Refusing to create a directory outside the output path.'));
}

return makeDir(dir);
});
};

const extractFile = (input, output, opts) => runPlugins(input, opts).then(files => {
if (opts.strip > 0) {
files = files
Expand Down Expand Up @@ -47,13 +62,16 @@ const extractFile = (input, output, opts) => runPlugins(input, opts).then(files
const now = new Date();

if (x.type === 'directory') {
return makeDir(dest)
return makeDir(output)
.then(outputPath => fsP.realpath(outputPath))
.then(realOutputPath => safeMakeDir(dest, realOutputPath))
.then(() => fsP.utimes(dest, now, x.mtime))
.then(() => x);
}

return makeDir(output)
.then(() => makeDir(path.dirname(dest)))
.then(outputPath => fsP.realpath(outputPath))
.then(realOutputPath => safeMakeDir(path.dirname(dest), realOutputPath))
.then(() => {
return Promise.all([fsP.realpath(path.dirname(dest)), fsP.realpath(output)])
.then(([realDestinationDir, realOutputDir]) => {
Expand Down
10 changes: 8 additions & 2 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,19 @@ test('return emptpy array if no plugins are set', async t => {
test('throw when a location outside the root is given', async t => {
await t.throwsAsync(async () => {
await m(path.join(__dirname, 'fixtures', 'slipping.tar.gz'), 'dist');
}, {message: /Refusing to write/});
}, {message: /Refusing/});
});

test('throw when a location outside the root including symlinks is given', async t => {
await t.throwsAsync(async () => {
await m(path.join(__dirname, 'fixtures', 'slip.zip'), 'dist');
}, {message: /Refusing to write/});
}, {message: /Refusing/});
});

test('throw when a directory outside the root including symlinks is given', async t => {
await t.throwsAsync(async () => {
await m(path.join(__dirname, 'fixtures', 'slipping_directory.tar.gz'), 'dist');
}, {message: /Refusing/});
});

test('allows filenames and directories to be written with dots in their names', async t => {
Expand Down

0 comments on commit 8850e7e

Please sign in to comment.