From c893d3072f7d31243b750b1d599b0826b8aaefa4 Mon Sep 17 00:00:00 2001 From: bcoe Date: Fri, 13 Mar 2020 13:54:02 -0700 Subject: [PATCH] fix: backport __proto__ fixes --- index.js | 23 ++++++++++++++++++----- package.json | 2 +- test/fixtures/config.json | 11 ++++++++++- test/yargs-parser.js | 26 ++++++++++++++++++++++++++ 4 files changed, 55 insertions(+), 7 deletions(-) diff --git a/index.js b/index.js index a5f7ae41..72685532 100644 --- a/index.js +++ b/index.js @@ -417,7 +417,7 @@ function parse (args, opts) { setKey(argv, splitKey, value) // handle populating aliases of the full key - if (flags.aliases[key]) { + if (flags.aliases[key] && flags.aliases[key].forEach) { flags.aliases[key].forEach(function (x) { x = x.split('.') setKey(argv, x, value) @@ -657,6 +657,10 @@ function parse (args, opts) { if (!configuration['dot-notation']) keys = [keys.join('.')] keys.slice(0, -1).forEach(function (key, index) { + // TODO(bcoe): in the next major version of yargs, switch to + // Object.create(null) for dot notation: + key = sanitizeKey(key) + if (typeof o === 'object' && o[key] === undefined) { o[key] = {} } @@ -676,11 +680,13 @@ function parse (args, opts) { } }) - var key = keys[keys.length - 1] + // TODO(bcoe): in the next major version of yargs, switch to + // Object.create(null) for dot notation: + const key = sanitizeKey(keys[keys.length - 1]) - var isTypeArray = checkAllAliases(keys.join('.'), flags.arrays) - var isValueArray = Array.isArray(value) - var duplicate = configuration['duplicate-arguments-array'] + const isTypeArray = checkAllAliases(keys.join('.'), flags.arrays) + const isValueArray = Array.isArray(value) + let duplicate = configuration['duplicate-arguments-array'] // nargs has higher priority than duplicate if (!duplicate && checkAllAliases(key, flags.nargs)) { @@ -952,4 +958,11 @@ Parser.detailed = function (args, opts) { return parse(args.slice(), opts) } +// TODO(bcoe): in the next major version of yargs, switch to +// Object.create(null) for dot notation: +function sanitizeKey (key) { + if (key === '__proto__') return '___proto___' + return key +} + module.exports = Parser diff --git a/package.json b/package.json index f2914039..ca9e91be 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "yargs-parser", - "version": "15.0.0", + "version": "15.0.1", "description": "the mighty option parser used by yargs", "main": "index.js", "scripts": { diff --git a/test/fixtures/config.json b/test/fixtures/config.json index 43376463..7065ae61 100644 --- a/test/fixtures/config.json +++ b/test/fixtures/config.json @@ -3,5 +3,14 @@ "z": 55, "foo": "baz", "version": "1.0.2", - "truthy": true + "truthy": true, + "toString": "method name", + "__proto__": { + "aaa": 99 + }, + "bar": { + "__proto__": { + "bbb": 100 + } + } } diff --git a/test/yargs-parser.js b/test/yargs-parser.js index 349549b4..dd3f22e2 100644 --- a/test/yargs-parser.js +++ b/test/yargs-parser.js @@ -429,6 +429,25 @@ describe('yargs-parser', function () { describe('config', function () { var jsonPath = path.resolve(__dirname, './fixtures/config.json') + it('should not pollute the prototype', function () { + const argv = parser(['--foo', 'bar'], { + alias: { + z: 'zoom' + }, + default: { + settings: jsonPath + }, + config: 'settings' + }) + + argv.should.have.property('herp', 'derp') + argv.should.have.property('zoom', 55) + argv.should.have.property('foo').and.deep.equal('bar') + + expect({}.bbb).to.equal(undefined) + expect({}.aaa).to.equal(undefined) + }) + // See: https://github.com/chevex/yargs/issues/12 it('should load options and values from default config if specified', function () { var argv = parser(['--foo', 'bar'], { @@ -3275,4 +3294,11 @@ describe('yargs-parser', function () { }) }) }) + + it('should not pollute the prototype', function () { + parser(['-f.__proto__.foo', '99', '-x.y.__proto__.bar', '100', '--__proto__', '200']) + Object.keys({}.__proto__).length.should.equal(0) // eslint-disable-line + expect({}.foo).to.equal(undefined) + expect({}.bar).to.equal(undefined) + }) })