Skip to content

Commit e799ba5

Browse files
committed
[Fix] parse: ignore __proto__ keys (#428)
1 parent 02ca358 commit e799ba5

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
@@ -135,7 +135,7 @@ var parseObject = function (chain, val, options, valuesParsed) {
135135
) {
136136
obj = [];
137137
obj[index] = leaf;
138-
} else {
138+
} else if (cleanRoot !== '__proto__') {
139139
obj[cleanRoot] = leaf;
140140
}
141141
}

test/parse.js

+60
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,66 @@ test('parse()', function (t) {
620620
st.end();
621621
});
622622

623+
t.test('dunder proto is ignored', function (st) {
624+
var payload = 'categories[__proto__]=login&categories[__proto__]&categories[length]=42';
625+
var result = qs.parse(payload, { allowPrototypes: true });
626+
627+
st.deepEqual(
628+
result,
629+
{
630+
categories: {
631+
length: '42'
632+
}
633+
},
634+
'silent [[Prototype]] payload'
635+
);
636+
637+
var plainResult = qs.parse(payload, { allowPrototypes: true, plainObjects: true });
638+
639+
st.deepEqual(
640+
plainResult,
641+
{
642+
__proto__: null,
643+
categories: {
644+
__proto__: null,
645+
length: '42'
646+
}
647+
},
648+
'silent [[Prototype]] payload: plain objects'
649+
);
650+
651+
var query = qs.parse('categories[__proto__]=cats&categories[__proto__]=dogs&categories[some][json]=toInject', { allowPrototypes: true });
652+
653+
st.notOk(Array.isArray(query.categories), 'is not an array');
654+
st.notOk(query.categories instanceof Array, 'is not instanceof an array');
655+
st.deepEqual(query.categories, { some: { json: 'toInject' } });
656+
st.equal(JSON.stringify(query.categories), '{"some":{"json":"toInject"}}', 'stringifies as a non-array');
657+
658+
st.deepEqual(
659+
qs.parse('foo[__proto__][hidden]=value&foo[bar]=stuffs', { allowPrototypes: true }),
660+
{
661+
foo: {
662+
bar: 'stuffs'
663+
}
664+
},
665+
'hidden values'
666+
);
667+
668+
st.deepEqual(
669+
qs.parse('foo[__proto__][hidden]=value&foo[bar]=stuffs', { allowPrototypes: true, plainObjects: true }),
670+
{
671+
__proto__: null,
672+
foo: {
673+
__proto__: null,
674+
bar: 'stuffs'
675+
}
676+
},
677+
'hidden values: plain objects'
678+
);
679+
680+
st.end();
681+
});
682+
623683
t.test('can return null objects', { skip: !Object.create }, function (st) {
624684
var expected = Object.create(null);
625685
expected.a = Object.create(null);

0 commit comments

Comments
 (0)