Skip to content

Commit ba24e74

Browse files
committed
[Fix] parse: ignore __proto__ keys (#428)
1 parent f047c9d commit ba24e74

File tree

2 files changed

+61
-1
lines changed

2 files changed

+61
-1
lines changed

lib/parse.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ var parseObject = function parseObject(chain, val, options) {
6868
) {
6969
obj = [];
7070
obj[index] = parseObject(chain, val, options);
71-
} else {
71+
} else if (cleanRoot !== '__proto__') {
7272
obj[cleanRoot] = parseObject(chain, val, options);
7373
}
7474
}

test/parse.js

+60
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,66 @@ test('parse()', function (t) {
476476
st.end();
477477
});
478478

479+
t.test('dunder proto is ignored', function (st) {
480+
var payload = 'categories[__proto__]=login&categories[__proto__]&categories[length]=42';
481+
var result = qs.parse(payload, { allowPrototypes: true });
482+
483+
st.deepEqual(
484+
result,
485+
{
486+
categories: {
487+
length: '42'
488+
}
489+
},
490+
'silent [[Prototype]] payload'
491+
);
492+
493+
var plainResult = qs.parse(payload, { allowPrototypes: true, plainObjects: true });
494+
495+
st.deepEqual(
496+
plainResult,
497+
{
498+
__proto__: null,
499+
categories: {
500+
__proto__: null,
501+
length: '42'
502+
}
503+
},
504+
'silent [[Prototype]] payload: plain objects'
505+
);
506+
507+
var query = qs.parse('categories[__proto__]=cats&categories[__proto__]=dogs&categories[some][json]=toInject', { allowPrototypes: true });
508+
509+
st.notOk(Array.isArray(query.categories), 'is not an array');
510+
st.notOk(query.categories instanceof Array, 'is not instanceof an array');
511+
st.deepEqual(query.categories, { some: { json: 'toInject' } });
512+
st.equal(JSON.stringify(query.categories), '{"some":{"json":"toInject"}}', 'stringifies as a non-array');
513+
514+
st.deepEqual(
515+
qs.parse('foo[__proto__][hidden]=value&foo[bar]=stuffs', { allowPrototypes: true }),
516+
{
517+
foo: {
518+
bar: 'stuffs'
519+
}
520+
},
521+
'hidden values'
522+
);
523+
524+
st.deepEqual(
525+
qs.parse('foo[__proto__][hidden]=value&foo[bar]=stuffs', { allowPrototypes: true, plainObjects: true }),
526+
{
527+
__proto__: null,
528+
foo: {
529+
__proto__: null,
530+
bar: 'stuffs'
531+
}
532+
},
533+
'hidden values: plain objects'
534+
);
535+
536+
st.end();
537+
});
538+
479539
t.test('can return null objects', { skip: !Object.create }, function (st) {
480540
var expected = Object.create(null);
481541
expected.a = Object.create(null);

0 commit comments

Comments
 (0)