Skip to content

Commit 7b0ddc2

Browse files
committedFeb 22, 2021
fix: prototype pollution
1 parent 8686d85 commit 7b0ddc2

File tree

6 files changed

+27
-4
lines changed

6 files changed

+27
-4
lines changed
 

‎dist/merge.browser.min.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎dist/merge.browser.test.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,13 @@ exports.isPlainObject = isPlainObject;
6262
function _recursiveMerge(base, extend) {
6363
if (!isPlainObject(base))
6464
return extend;
65-
for (var key in extend)
65+
for (var key in extend) {
66+
if (key === '__proto__' || key === 'constructor' || key === 'prototype')
67+
continue;
6668
base[key] = (isPlainObject(base[key]) && isPlainObject(extend[key])) ?
6769
_recursiveMerge(base[key], extend[key]) :
6870
extend[key];
71+
}
6972
return base;
7073
}
7174
function _merge(isClone, isRecursive, items) {
@@ -194,6 +197,9 @@ describe('merge.recursive', function () {
194197
});
195198
it('prototype pollution attack', function () {
196199
chai_1.assert.deepEqual(index_1.default.recursive({}, JSON.parse('{"__proto__": {"a": true}}')), {});
200+
chai_1.assert.equal({}['a'], undefined);
201+
chai_1.assert.deepEqual(index_1.default.recursive({ deep: {} }, JSON.parse('{ "deep": { "__proto__": {"b": true} }}')), { deep: {} });
202+
chai_1.assert.equal({}['b'], undefined);
197203
});
198204
});
199205

‎lib/src/index.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,13 @@ exports.isPlainObject = isPlainObject;
5555
function _recursiveMerge(base, extend) {
5656
if (!isPlainObject(base))
5757
return extend;
58-
for (var key in extend)
58+
for (var key in extend) {
59+
if (key === '__proto__' || key === 'constructor' || key === 'prototype')
60+
continue;
5961
base[key] = (isPlainObject(base[key]) && isPlainObject(extend[key])) ?
6062
_recursiveMerge(base[key], extend[key]) :
6163
extend[key];
64+
}
6265
return base;
6366
}
6467
function _merge(isClone, isRecursive, items) {

‎lib/test/index.js

+3
Original file line numberDiff line numberDiff line change
@@ -99,5 +99,8 @@ describe('merge.recursive', function () {
9999
});
100100
it('prototype pollution attack', function () {
101101
chai_1.assert.deepEqual(index_1.default.recursive({}, JSON.parse('{"__proto__": {"a": true}}')), {});
102+
chai_1.assert.equal({}['a'], undefined);
103+
chai_1.assert.deepEqual(index_1.default.recursive({ deep: {} }, JSON.parse('{ "deep": { "__proto__": {"b": true} }}')), { deep: {} });
104+
chai_1.assert.equal({}['b'], undefined);
102105
});
103106
});

‎src/index.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,12 @@ function _recursiveMerge(base: any, extend: any) {
6161
if (!isPlainObject(base))
6262
return extend
6363

64-
for (const key in extend)
64+
for (const key in extend) {
65+
if (key === '__proto__' || key === 'constructor' || key === 'prototype') continue
6566
base[key] = (isPlainObject(base[key]) && isPlainObject(extend[key])) ?
6667
_recursiveMerge(base[key], extend[key]) :
6768
extend[key]
69+
}
6870

6971
return base
7072

‎test/index.ts

+9
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,15 @@ describe('merge.recursive', function () {
219219
{}
220220
)
221221

222+
assert.equal(({} as any)['a'], undefined)
223+
224+
assert.deepEqual(
225+
merge.recursive({ deep: {} }, JSON.parse('{ "deep": { "__proto__": {"b": true} }}')),
226+
{ deep: {} }
227+
)
228+
229+
assert.equal(({} as any)['b'], undefined)
230+
222231
})
223232

224233
})

0 commit comments

Comments
 (0)
Please sign in to comment.