CVE-2017-1001003 (JavaScript, published 2017-11-27T14:29Z)
Description: value: math.js before 3.17.0 had an issue where private properties such as a constructor could be replaced by using unicode characters when creating an object.
Severity: HIGH (CVSS v3 base score: 9.8)
Weakness: CWE-20 \u2014 Improper Input Validation
The product receives input or data, but it does
        not validate or incorrectly validates that the input has the
        properties that are required to process the data safely and
        correctly.
Repository: https://github.com/josdejong/mathjs
Files changed:
HISTORY.md
lib/expression/node/ObjectNode.js
test/expression/security.test.js
test/utils/customs.test.js
Commit message: Fixed a security issue where forbidden properties like constructor could be replaced by using unicode characters when creating an object


Vulnerable code:
        if (!isSafeProperty(node.properties, key)) {
          throw new Error('No access to property "' + key + '"');
        entries.push(stringify(key) + ': ' + compile(node.properties[key], defs, args));

Fixed code:
- Fixed a security issue where forbidden properties like constructor could be
  replaced by using unicode characters when creating an object. No known exploit,
  but could possibly allow arbitrary code execution. Thanks Masato Kinugawa.
        // we stringify/parse the key here to resolve unicode characters,
        // so you cannot create a key like {"co\\u006Estructor": null} 
        var stringifiedKey = stringify(key)
        var parsedKey = JSON.parse(stringifiedKey)
        if (!isSafeProperty(node.properties, parsedKey)) {
          throw new Error('No access to property "' + parsedKey + '"');
        entries.push(stringifiedKey + ': ' + compile(node.properties[key], defs, args));
  it ('should not allow disguising forbidden properties with unicode characters', function () {
    var scope = {
      a: {}
    };

    assert.throws(function () { math.eval('a.co\u006Estructor', scope); }, /Error: No access to property "constructor"/);
    assert.throws(function () { math.eval('a["co\\u006Estructor"]', scope); }, /Error: No access to property "constructor"/);
    assert.throws(function () { math.eval('a.constructor', scope); }, /Error: No access to property "constructor"/);
    assert.throws(function () { math.eval('a.constructor = 2', scope); }, /Error: No access to property "constructor"/);
    assert.throws(function () { math.eval('a["constructor"] = 2', scope); }, /Error: No access to property "constructor"/);
    assert.throws(function () { math.eval('a["co\\u006Estructor"] = 2', scope); }, /Error: No access to property "constructor"/);
    assert.throws(function () { math.eval('a = {"constructor": 2}', scope); }, /Error: No access to property "constructor"/);
    assert.throws(function () { math.eval('a = {constructor: 2}', scope); }, /Error: No access to property "constructor"/);
    assert.throws(function () { math.eval('a = {"co\\u006Estructor": 2}', scope); }, /Error: No access to property "constructor"/);
    assert.throws(function () { math.eval('a = {co\u006Estructor: 2}', scope); }, /Error: No access to property "constructor"/);
  })


      // method with unicode chars
      assert.equal(customs.isSafeMethod(matrix, 'co\u006Estructor'), false);
      // property with unicode chars
      assert.equal(customs.isSafeProperty(object, 'co\u006Estructor'), false);