Skip to content

Commit ecb8051

Browse files
committed
Fix object pollution vulnerability in math.config
1 parent a2858e2 commit ecb8051

File tree

4 files changed

+44
-1
lines changed

4 files changed

+44
-1
lines changed

HISTORY.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# History
22

3+
# not yet published, version 7.5.1
4+
5+
- Fix object pollution vulnerability in `math.config`. Thanks Snyk.
6+
7+
38
# 2020-10-07, version 7.5.0
49

510
- Function `pickRandom` now allows randomly picking elements from matrices

src/utils/object.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,9 @@ export function deepExtend (a, b) {
8686
}
8787

8888
for (const prop in b) {
89-
if (hasOwnProperty(b, prop)) {
89+
// We check against prop not being in Object.prototype or Function.prototype
90+
// to prevent polluting for example Object.__proto__.
91+
if (hasOwnProperty(b, prop) && !(prop in Object.prototype) && !(prop in Function.prototype)) {
9092
if (b[prop] && b[prop].constructor === Object) {
9193
if (a[prop] === undefined) {
9294
a[prop] = {}

test/unit-tests/expression/security.test.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,34 @@ describe('security', function () {
390390
assert.strictEqual(math.expression.mathWithTransform.chain, undefined)
391391
assert.deepStrictEqual(math.evaluate('chain'), math.unit('chain'))
392392
})
393+
394+
it('should not allow polluting the Object prototype via config', () => {
395+
const obj = {}
396+
assert.strictEqual(obj.polluted, undefined)
397+
398+
// change the configuration
399+
const newConfig = JSON.parse('{"__proto__":{"polluted":"yes"}}')
400+
math.config(newConfig)
401+
assert.strictEqual(obj.polluted, undefined)
402+
})
403+
404+
it('should not allow polluting the Object prototype via config via the expression parser', () => {
405+
const obj = {}
406+
assert.strictEqual(obj.polluted, undefined)
407+
408+
// change the configuration
409+
math.evaluate('config({"__proto__":{"polluted":"yes"}})')
410+
assert.strictEqual(obj.polluted, undefined)
411+
})
412+
413+
it('should not allow polluting the Object prototype by creating an object in the expression parser', () => {
414+
const obj = {}
415+
assert.strictEqual(obj.polluted, undefined)
416+
417+
// change the configuration
418+
math.evaluate('a = {"__proto__":{"polluted":"yes"}}')
419+
assert.strictEqual(obj.polluted, undefined)
420+
})
393421
})
394422

395423
function isPlainObject (object) {

test/unit-tests/utils/object.test.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,14 @@ describe('object', function () {
141141

142142
delete Object.prototype.foo
143143
})
144+
145+
it('should not pollute Object.__proto__', function () {
146+
const obj = {}
147+
assert.strictEqual(obj.polluted, undefined)
148+
149+
deepExtend(obj, JSON.parse('{"__proto__":{"polluted":"yes"}}'))
150+
assert.strictEqual(obj.polluted, undefined)
151+
})
144152
})
145153

146154
describe('deepEqual', function () {

0 commit comments

Comments
 (0)