Skip to content

Commit 85acab9

Browse files
committed
Harden options to prevent path traversal when passed untrusted input
This is not fixing any vulnerability since these options are not meant to accept untrusted input.
1 parent 91afd2a commit 85acab9

File tree

2 files changed

+12
-3
lines changed

2 files changed

+12
-3
lines changed

index.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ import {isStream} from 'is-stream';
99

1010
const pipeline = promisify(stream.pipeline); // TODO: Use `node:stream/promises` when targeting Node.js 16.
1111

12-
const getPath = (prefix = '') => path.join(tempDir, prefix + uniqueString());
12+
// Use `path.basename()` to prevent path traversal.
13+
const getPath = (prefix = '') => path.join(tempDir, path.basename(prefix) + uniqueString());
1314

1415
const writeStream = async (filePath, data) => pipeline(data, fs.createWriteStream(filePath));
1516

@@ -27,10 +28,12 @@ export function temporaryFile({name, extension} = {}) {
2728
throw new Error('The `name` and `extension` options are mutually exclusive');
2829
}
2930

30-
return path.join(temporaryDirectory(), name);
31+
// Use `path.basename()` to prevent path traversal.
32+
return path.join(temporaryDirectory(), path.basename(name));
3133
}
3234

33-
return getPath() + (extension === undefined || extension === null ? '' : '.' + extension.replace(/^\./, ''));
35+
// Use `path.basename()` to prevent path traversal.
36+
return getPath() + (extension === undefined || extension === null ? '' : '.' + path.basename(extension).replace(/^\./, ''));
3437
}
3538

3639
export const temporaryFileTask = async (callback, options) => runTask(temporaryFile(options), callback);

test.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,3 +140,9 @@ test('.root', t => {
140140
t.true(rootTemporaryDirectory.length > 0);
141141
t.true(path.isAbsolute(rootTemporaryDirectory));
142142
});
143+
144+
test('path traversal prevention', t => {
145+
t.true(temporaryFile({name: '../../../test'}).includes(tempDir));
146+
t.true(temporaryFile({extension: '../../../test'}).includes(tempDir));
147+
t.true(temporaryDirectory({prefix: '../../../test'}).includes(tempDir));
148+
});

0 commit comments

Comments
 (0)