89 lines
3.0 KiB
Diff
89 lines
3.0 KiB
Diff
--- lib/tmp.js
|
|
@@ -525,6 +525,19 @@ function _generateTmpName(opts) {
|
|
return path.join(tmpDir, opts.dir, name);
|
|
}
|
|
|
|
+/**
|
|
+ * Check the prefix and postfix options
|
|
+ *
|
|
+ * @private
|
|
+ */
|
|
+function _assertPath(path) {
|
|
+ if (path.includes("..")) {
|
|
+ throw new Error("Relative value not allowed");
|
|
+ }
|
|
+
|
|
+ return path;
|
|
+}
|
|
+
|
|
/**
|
|
* Asserts and sanitizes the basic options.
|
|
*
|
|
@@ -539,8 +552,9 @@ function _assertOptionsBase(options) {
|
|
|
|
// must not fail on valid .<name> or ..<name> or similar such constructs
|
|
const basename = path.basename(name);
|
|
- if (basename === '..' || basename === '.' || basename !== name)
|
|
+ if (basename === '..' || basename === '.' || basename !== name) {
|
|
throw new Error(`name option must not contain a path, found "${name}".`);
|
|
+ }
|
|
}
|
|
|
|
/* istanbul ignore else */
|
|
@@ -561,8 +575,9 @@ function _assertOptionsBase(options) {
|
|
options.unsafeCleanup = !!options.unsafeCleanup;
|
|
|
|
// for completeness' sake only, also keep (multiple) blanks if the user, purportedly sane, requests us to
|
|
- options.prefix = _isUndefined(options.prefix) ? '' : options.prefix;
|
|
- options.postfix = _isUndefined(options.postfix) ? '' : options.postfix;
|
|
+ options.prefix = _isUndefined(options.prefix) ? '' : _assertPath(options.prefix);
|
|
+ options.postfix = _isUndefined(options.postfix) ? '' : _assertPath(options.postfix);
|
|
+ options.template = _isUndefined(options.template) ? undefined : _assertPath(options.template);
|
|
}
|
|
|
|
/**
|
|
@@ -578,7 +593,7 @@ function _getRelativePath(option, name, tmpDir, cb) {
|
|
|
|
const relativePath = path.relative(tmpDir, resolvedPath);
|
|
|
|
- if (!resolvedPath.startsWith(tmpDir)) {
|
|
+ if (relativePath.startsWith('..') || path.isAbsolute(relativePath)) {
|
|
return cb(new Error(`${option} option must be relative to "${tmpDir}", found "${relativePath}".`));
|
|
}
|
|
|
|
@@ -597,7 +612,7 @@ function _getRelativePathSync(option, name, tmpDir) {
|
|
const resolvedPath = _resolvePathSync(name, tmpDir);
|
|
const relativePath = path.relative(tmpDir, resolvedPath);
|
|
|
|
- if (!resolvedPath.startsWith(tmpDir)) {
|
|
+ if (relativePath.startsWith('..') || path.isAbsolute(relativePath)) {
|
|
throw new Error(`${option} option must be relative to "${tmpDir}", found "${relativePath}".`);
|
|
}
|
|
|
|
|
|
--- test/GHSA-ph9p-34f9-6g65-test.js
|
|
@@ -0,0 +1,24 @@
|
|
+const assert = require('assert');
|
|
+const tmp = require('../lib/tmp');
|
|
+
|
|
+describe('GHSA-ph9p-34f9-6g65', function () {
|
|
+ describe('#fileSync with attacker `prefix`', function () {
|
|
+ it('should not allow such prefixes', function (done) {
|
|
+ assert.throws(function () {
|
|
+ tmp.fileSync({ prefix: "../foo"});
|
|
+ }, new RegExp('^Error: Relative value not allowed'));
|
|
+
|
|
+ done();
|
|
+ });
|
|
+ });
|
|
+
|
|
+ describe('#fileSync with attacker `postfix`', function () {
|
|
+ it('should not allow such prefixes', function (done) {
|
|
+ assert.throws(function () {
|
|
+ tmp.fileSync({ postfix: "../foo"});
|
|
+ }, new RegExp('^Error: Relative value not allowed'));
|
|
+
|
|
+ done();
|
|
+ });
|
|
+ });
|
|
+});
|