Skip to content

Commit 3c3517d

Browse files
committed
More security fixes + unit tests
1 parent 43c4fe9 commit 3c3517d

3 files changed

Lines changed: 56 additions & 10 deletions

File tree

HISTORY.md

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

33

4+
## 2017-03-31, version 3.10.3
5+
6+
- More security fixes related to the ones fixed in `v3.10.2`.
7+
8+
49
## 2017-03-31, version 3.10.2
510

611
- Fixed a security vulnerability in the expression parser allowing

lib/expression/node/FunctionNode.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -428,19 +428,32 @@ function factory (type, config, load, typed, math) {
428428
* else throws an error
429429
*/
430430
function customs (fn) {
431+
if (fn === jsEval) {
432+
throw new Error('Calling "eval" is not allowed');
433+
}
434+
431435
if (fn === Function) {
432436
throw new Error('Calling "Function" is not allowed');
433437
}
434438

435-
if (fn === jsEval) {
436-
throw new Error('Calling "eval" is not allowed');
439+
if (fn === Function.apply) {
440+
throw new Error('Calling "apply" is not allowed');
441+
}
442+
443+
if (fn === Function.call) {
444+
throw new Error('Calling "call" is not allowed');
445+
}
446+
447+
if (fn === Function.bind) {
448+
throw new Error('Calling "bind" is not allowed');
437449
}
438450

439451
// this function is ok
440452
return fn;
441453
}
442454

443455
var jsEval = eval
456+
var jsApply = eval
444457

445458
exports.name = 'FunctionNode';
446459
exports.path = 'expression.node';

test/expression/parse.test.js

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2043,28 +2043,56 @@ describe('parse', function() {
20432043

20442044
describe('security', function () {
20452045

2046-
it ('should not allow calling Function from an object property', function () {
2046+
it ('should not allow calling Function/eval via a symbol', function () {
20472047
assert.throws(function () {
2048-
math.eval('[].map.constructor("console.log(\\"hacked...\\")")()')
2048+
math.eval('disguised("console.log(\\"hacked...\\")")()', {disguised: eval})
2049+
}, /Error: Calling "eval" is not allowed/)
2050+
2051+
assert.throws(function () {
2052+
math.eval('disguised("console.log(\\"hacked...\\")")()', {disguised: Function})
20492053
}, /Error: Calling "Function" is not allowed/)
20502054
})
20512055

2052-
it ('should not allow calling Function', function () {
2056+
it ('should not allow calling Function/eval via an object property', function () {
2057+
assert.throws(function () {
2058+
math.eval('[].map.constructor("console.log(\\"hacked...\\")")()')
2059+
}, /Error: Calling "Function" is not allowed/)
2060+
2061+
assert.throws(function () {
2062+
math.eval('obj.disguised("console.log(\\"hacked...\\")")()', {obj: {disguised: eval}})
2063+
}, /Error: Calling "eval" is not allowed/)
2064+
20532065
assert.throws(function () {
2054-
math.eval('disguised("console.log(\\"hacked...\\")")()', {disguised: Function})
20552066
math.eval('obj.disguised("console.log(\\"hacked...\\")")()', {obj: {disguised: Function}})
2056-
math.eval('fn()("console.log(\\"hacked...\\")")()', {fn: function () {return Function}})
20572067
}, /Error: Calling "Function" is not allowed/)
20582068
})
20592069

2060-
it ('should not allow calling eval', function () {
2070+
it ('should not allow calling Function/eval when returned by a function', function () {
2071+
assert.throws(function () {
2072+
math.eval('fn()("console.log(\\"hacked...\\")")()', {fn: function () {return Function}})
2073+
}, /Error: Calling "Function" is not allowed/)
2074+
20612075
assert.throws(function () {
2062-
math.eval('disguised("console.log(\\"hacked...\\")")()', {disguised: eval})
2063-
math.eval('obj.disguised("console.log(\\"hacked...\\")")()', {obj: {disguised: eval}})
20642076
math.eval('fn()("console.log(\\"hacked...\\")")()', {fn: function () {return eval}})
20652077
}, /Error: Calling "eval" is not allowed/)
20662078
})
20672079

2080+
it ('should not allow calling Function/eval via call/apply', function () {
2081+
assert.throws(function () {
2082+
math.eval('[].map.constructor.call(null, "console.log(\\"hacked...\\")")()')
2083+
}, /Error: Calling "call" is not allowed/)
2084+
2085+
assert.throws(function () {
2086+
math.eval('[].map.constructor.apply(null, ["console.log(\\"hacked...\\")"])()')
2087+
}, /Error: Calling "apply" is not allowed/)
2088+
})
2089+
2090+
it ('should not allow calling Function/eval via bind', function () {
2091+
assert.throws(function () {
2092+
math.eval('[].map.constructor.bind()("console.log(\\"hacked...\\")")()')
2093+
}, /Error: Calling "bind" is not allowed/)
2094+
})
2095+
20682096
});
20692097

20702098
});

0 commit comments

Comments
 (0)