Skip to content

Commit 63810ca

Browse files
authored
fix: __proto__ will now be replaced with ___proto___ in parse (#258)
1 parent 48b6d9c commit 63810ca

File tree

3 files changed

+70
-2
lines changed

3 files changed

+70
-2
lines changed

index.js

+15-1
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,10 @@ function parse (args, opts) {
697697
if (!configuration['dot-notation']) keys = [keys.join('.')]
698698

699699
keys.slice(0, -1).forEach(function (key, index) {
700+
// TODO(bcoe): in the next major version of yargs, switch to
701+
// Object.create(null) for dot notation:
702+
key = sanitizeKey(key)
703+
700704
if (typeof o === 'object' && o[key] === undefined) {
701705
o[key] = {}
702706
}
@@ -716,7 +720,10 @@ function parse (args, opts) {
716720
}
717721
})
718722

719-
const key = keys[keys.length - 1]
723+
// TODO(bcoe): in the next major version of yargs, switch to
724+
// Object.create(null) for dot notation:
725+
const key = sanitizeKey(keys[keys.length - 1])
726+
720727
const isTypeArray = checkAllAliases(keys.join('.'), flags.arrays)
721728
const isValueArray = Array.isArray(value)
722729
let duplicate = configuration['duplicate-arguments-array']
@@ -1001,4 +1008,11 @@ Parser.detailed = function (args, opts) {
10011008
return parse(args.slice(), opts)
10021009
}
10031010

1011+
// TODO(bcoe): in the next major version of yargs, switch to
1012+
// Object.create(null) for dot notation:
1013+
function sanitizeKey (key) {
1014+
if (key === '__proto__') return '___proto___'
1015+
return key
1016+
}
1017+
10041018
module.exports = Parser

test/fixtures/config.json

+9-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,13 @@
44
"foo": "baz",
55
"version": "1.0.2",
66
"truthy": true,
7-
"toString": "method name"
7+
"toString": "method name",
8+
"__proto__": {
9+
"aaa": 99
10+
},
11+
"bar": {
12+
"__proto__": {
13+
"bbb": 100
14+
}
15+
}
816
}

test/yargs-parser.js

+46
Original file line numberDiff line numberDiff line change
@@ -727,6 +727,25 @@ describe('yargs-parser', function () {
727727

728728
argv.error.message.should.equal('someone set us up the bomb')
729729
})
730+
731+
it('should not pollute the prototype', function () {
732+
const argv = parser(['--foo', 'bar'], {
733+
alias: {
734+
z: 'zoom'
735+
},
736+
default: {
737+
settings: jsonPath
738+
},
739+
config: 'settings'
740+
})
741+
742+
argv.should.have.property('herp', 'derp')
743+
argv.should.have.property('zoom', 55)
744+
argv.should.have.property('foo').and.deep.equal('bar')
745+
746+
expect({}.bbb).to.equal(undefined)
747+
expect({}.aaa).to.equal(undefined)
748+
})
730749
})
731750

732751
describe('config objects', function () {
@@ -974,6 +993,13 @@ describe('yargs-parser', function () {
974993
argv.f.foo.should.eql(99)
975994
argv.f.bar.should.eql(true)
976995
})
996+
997+
it('should not pollute the prototype', function () {
998+
parser(['-f.__proto__.foo', '99', '-x.y.__proto__.bar', '100', '--__proto__', '200'])
999+
Object.keys({}.__proto__).length.should.equal(0) // eslint-disable-line
1000+
expect({}.foo).to.equal(undefined)
1001+
expect({}.bar).to.equal(undefined)
1002+
})
9771003
})
9781004

9791005
it('should set boolean and alias using explicit true', function () {
@@ -3702,4 +3728,24 @@ describe('yargs-parser', function () {
37023728
argv._.should.eql([101, 102])
37033729
})
37043730
})
3731+
3732+
it('should replace the key __proto__ with the key ___proto___', function () {
3733+
const argv = parser(['-f.__proto__.foo', '99', '-x.y.__proto__.bar', '100', '--__proto__', '200'])
3734+
argv.should.eql({
3735+
_: [],
3736+
___proto___: 200,
3737+
f: {
3738+
___proto___: {
3739+
foo: 99
3740+
}
3741+
},
3742+
x: {
3743+
y: {
3744+
___proto___: {
3745+
bar: 100
3746+
}
3747+
}
3748+
}
3749+
})
3750+
})
37053751
})

0 commit comments

Comments
 (0)