Skip to content

Commit 8b4cc14

Browse files
committed
[Fix] parse: ignore __proto__ keys
1 parent ad63d36 commit 8b4cc14

File tree

2 files changed

+61
-1
lines changed

2 files changed

+61
-1
lines changed

lib/parse.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ var parseObject = function (chain, val, options, valuesParsed) {
136136
) {
137137
obj = [];
138138
obj[index] = leaf;
139-
} else {
139+
} else if (cleanRoot !== '__proto__') {
140140
obj[cleanRoot] = leaf;
141141
}
142142
}

test/parse.js

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,66 @@ test('parse()', function (t) {
629629
st.end();
630630
});
631631

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

0 commit comments

Comments
 (0)