object-path
Advanced tools
Comparing version 0.11.7 to 0.11.8
282
index.js
@@ -1,20 +0,21 @@ | ||
(function (root, factory){ | ||
'use strict'; | ||
(function (root, factory) { | ||
'use strict' | ||
/*istanbul ignore next:cant test*/ | ||
if (typeof module === 'object' && typeof module.exports === 'object') { | ||
module.exports = factory(); | ||
module.exports = factory() | ||
} else if (typeof define === 'function' && define.amd) { | ||
// AMD. Register as an anonymous module. | ||
define([], factory); | ||
define([], factory) | ||
} else { | ||
// Browser globals | ||
root.objectPath = factory(); | ||
root.objectPath = factory() | ||
} | ||
})(this, function(){ | ||
'use strict'; | ||
})(this, function () { | ||
'use strict' | ||
var toStr = Object.prototype.toString; | ||
function hasOwnProperty(obj, prop) { | ||
if(obj == null) { | ||
var toStr = Object.prototype.toString | ||
function hasOwnProperty (obj, prop) { | ||
if (obj == null) { | ||
return false | ||
@@ -26,51 +27,51 @@ } | ||
function isEmpty(value){ | ||
function isEmpty (value) { | ||
if (!value) { | ||
return true; | ||
return true | ||
} | ||
if (isArray(value) && value.length === 0) { | ||
return true; | ||
return true | ||
} else if (typeof value !== 'string') { | ||
for (var i in value) { | ||
if (hasOwnProperty(value, i)) { | ||
return false; | ||
} | ||
for (var i in value) { | ||
if (hasOwnProperty(value, i)) { | ||
return false | ||
} | ||
return true; | ||
} | ||
return true | ||
} | ||
return false; | ||
return false | ||
} | ||
function toString(type){ | ||
return toStr.call(type); | ||
function toString (type) { | ||
return toStr.call(type) | ||
} | ||
function isObject(obj){ | ||
return typeof obj === 'object' && toString(obj) === "[object Object]"; | ||
function isObject (obj) { | ||
return typeof obj === 'object' && toString(obj) === '[object Object]' | ||
} | ||
var isArray = Array.isArray || function(obj){ | ||
var isArray = Array.isArray || function (obj) { | ||
/*istanbul ignore next:cant test*/ | ||
return toStr.call(obj) === '[object Array]'; | ||
return toStr.call(obj) === '[object Array]' | ||
} | ||
function isBoolean(obj){ | ||
return typeof obj === 'boolean' || toString(obj) === '[object Boolean]'; | ||
function isBoolean (obj) { | ||
return typeof obj === 'boolean' || toString(obj) === '[object Boolean]' | ||
} | ||
function getKey(key){ | ||
var intKey = parseInt(key); | ||
function getKey (key) { | ||
var intKey = parseInt(key) | ||
if (intKey.toString() === key) { | ||
return intKey; | ||
return intKey | ||
} | ||
return key; | ||
return key | ||
} | ||
function factory(options) { | ||
function factory (options) { | ||
options = options || {} | ||
var objectPath = function(obj) { | ||
return Object.keys(objectPath).reduce(function(proxy, prop) { | ||
if(prop === 'create') { | ||
return proxy; | ||
var objectPath = function (obj) { | ||
return Object.keys(objectPath).reduce(function (proxy, prop) { | ||
if (prop === 'create') { | ||
return proxy | ||
} | ||
@@ -80,8 +81,8 @@ | ||
if (typeof objectPath[prop] === 'function') { | ||
proxy[prop] = objectPath[prop].bind(objectPath, obj); | ||
proxy[prop] = objectPath[prop].bind(objectPath, obj) | ||
} | ||
return proxy; | ||
}, {}); | ||
}; | ||
return proxy | ||
}, {}) | ||
} | ||
@@ -99,32 +100,44 @@ var hasShallowProperty | ||
function getShallowProperty(obj, prop) { | ||
function getShallowProperty (obj, prop) { | ||
if (hasShallowProperty(obj, prop)) { | ||
return obj[prop]; | ||
return obj[prop] | ||
} | ||
} | ||
function set(obj, path, value, doNotReplace){ | ||
var getShallowPropertySafely | ||
if (options.includeInheritedProps) { | ||
getShallowPropertySafely = function (obj, currentPath) { | ||
if (typeof currentPath !== 'string' && typeof currentPath !== 'number') { | ||
currentPath = String(currentPath) | ||
} | ||
var currentValue = getShallowProperty(obj, currentPath) | ||
if (currentPath === '__proto__' || currentPath === 'prototype' || | ||
(currentPath === 'constructor' && typeof currentValue === 'function')) { | ||
throw new Error('For security reasons, object\'s magic properties cannot be set') | ||
} | ||
return currentValue | ||
} | ||
} else { | ||
getShallowPropertySafely = function (obj, currentPath) { | ||
return getShallowProperty(obj, currentPath) | ||
} | ||
} | ||
function set (obj, path, value, doNotReplace) { | ||
if (typeof path === 'number') { | ||
path = [path]; | ||
path = [path] | ||
} | ||
if (!path || path.length === 0) { | ||
return obj; | ||
return obj | ||
} | ||
if (typeof path === 'string') { | ||
return set(obj, path.split('.').map(getKey), value, doNotReplace); | ||
return set(obj, path.split('.').map(getKey), value, doNotReplace) | ||
} | ||
var currentPath = path[0]; | ||
if (typeof currentPath !== 'string' && typeof currentPath !== 'number') { | ||
currentPath = String(currentPath) | ||
} | ||
var currentValue = getShallowProperty(obj, currentPath); | ||
if (options.includeInheritedProps && (currentPath === '__proto__' || | ||
(currentPath === 'constructor' && typeof currentValue === 'function'))) { | ||
throw new Error('For security reasons, object\'s magic properties cannot be set') | ||
} | ||
var currentPath = path[0] | ||
var currentValue = getShallowPropertySafely(obj, currentPath) | ||
if (path.length === 1) { | ||
if (currentValue === void 0 || !doNotReplace) { | ||
obj[currentPath] = value; | ||
obj[currentPath] = value | ||
} | ||
return currentValue; | ||
return currentValue | ||
} | ||
@@ -134,10 +147,10 @@ | ||
//check if we assume an array | ||
if(typeof path[1] === 'number') { | ||
obj[currentPath] = []; | ||
if (typeof path[1] === 'number') { | ||
obj[currentPath] = [] | ||
} else { | ||
obj[currentPath] = {}; | ||
obj[currentPath] = {} | ||
} | ||
} | ||
return set(obj[currentPath], path.slice(1), value, doNotReplace); | ||
return set(obj[currentPath], path.slice(1), value, doNotReplace) | ||
} | ||
@@ -147,165 +160,166 @@ | ||
if (typeof path === 'number') { | ||
path = [path]; | ||
path = [path] | ||
} else if (typeof path === 'string') { | ||
path = path.split('.'); | ||
path = path.split('.') | ||
} | ||
if (!path || path.length === 0) { | ||
return !!obj; | ||
return !!obj | ||
} | ||
for (var i = 0; i < path.length; i++) { | ||
var j = getKey(path[i]); | ||
var j = getKey(path[i]) | ||
if((typeof j === 'number' && isArray(obj) && j < obj.length) || | ||
if ((typeof j === 'number' && isArray(obj) && j < obj.length) || | ||
(options.includeInheritedProps ? (j in Object(obj)) : hasOwnProperty(obj, j))) { | ||
obj = obj[j]; | ||
obj = obj[j] | ||
} else { | ||
return false; | ||
return false | ||
} | ||
} | ||
return true; | ||
}; | ||
return true | ||
} | ||
objectPath.ensureExists = function (obj, path, value){ | ||
return set(obj, path, value, true); | ||
}; | ||
objectPath.ensureExists = function (obj, path, value) { | ||
return set(obj, path, value, true) | ||
} | ||
objectPath.set = function (obj, path, value, doNotReplace){ | ||
return set(obj, path, value, doNotReplace); | ||
}; | ||
objectPath.set = function (obj, path, value, doNotReplace) { | ||
return set(obj, path, value, doNotReplace) | ||
} | ||
objectPath.insert = function (obj, path, value, at){ | ||
var arr = objectPath.get(obj, path); | ||
at = ~~at; | ||
objectPath.insert = function (obj, path, value, at) { | ||
var arr = objectPath.get(obj, path) | ||
at = ~~at | ||
if (!isArray(arr)) { | ||
arr = []; | ||
objectPath.set(obj, path, arr); | ||
arr = [] | ||
objectPath.set(obj, path, arr) | ||
} | ||
arr.splice(at, 0, value); | ||
}; | ||
arr.splice(at, 0, value) | ||
} | ||
objectPath.empty = function(obj, path) { | ||
objectPath.empty = function (obj, path) { | ||
if (isEmpty(path)) { | ||
return void 0; | ||
return void 0 | ||
} | ||
if (obj == null) { | ||
return void 0; | ||
return void 0 | ||
} | ||
var value, i; | ||
var value, i | ||
if (!(value = objectPath.get(obj, path))) { | ||
return void 0; | ||
return void 0 | ||
} | ||
if (typeof value === 'string') { | ||
return objectPath.set(obj, path, ''); | ||
return objectPath.set(obj, path, '') | ||
} else if (isBoolean(value)) { | ||
return objectPath.set(obj, path, false); | ||
return objectPath.set(obj, path, false) | ||
} else if (typeof value === 'number') { | ||
return objectPath.set(obj, path, 0); | ||
return objectPath.set(obj, path, 0) | ||
} else if (isArray(value)) { | ||
value.length = 0; | ||
value.length = 0 | ||
} else if (isObject(value)) { | ||
for (i in value) { | ||
if (hasShallowProperty(value, i)) { | ||
delete value[i]; | ||
delete value[i] | ||
} | ||
} | ||
} else { | ||
return objectPath.set(obj, path, null); | ||
return objectPath.set(obj, path, null) | ||
} | ||
}; | ||
} | ||
objectPath.push = function (obj, path /*, values */){ | ||
var arr = objectPath.get(obj, path); | ||
objectPath.push = function (obj, path /*, values */) { | ||
var arr = objectPath.get(obj, path) | ||
if (!isArray(arr)) { | ||
arr = []; | ||
objectPath.set(obj, path, arr); | ||
arr = [] | ||
objectPath.set(obj, path, arr) | ||
} | ||
arr.push.apply(arr, Array.prototype.slice.call(arguments, 2)); | ||
}; | ||
arr.push.apply(arr, Array.prototype.slice.call(arguments, 2)) | ||
} | ||
objectPath.coalesce = function (obj, paths, defaultValue) { | ||
var value; | ||
var value | ||
for (var i = 0, len = paths.length; i < len; i++) { | ||
if ((value = objectPath.get(obj, paths[i])) !== void 0) { | ||
return value; | ||
return value | ||
} | ||
} | ||
return defaultValue; | ||
}; | ||
return defaultValue | ||
} | ||
objectPath.get = function (obj, path, defaultValue){ | ||
objectPath.get = function (obj, path, defaultValue) { | ||
if (typeof path === 'number') { | ||
path = [path]; | ||
path = [path] | ||
} | ||
if (!path || path.length === 0) { | ||
return obj; | ||
return obj | ||
} | ||
if (obj == null) { | ||
return defaultValue; | ||
return defaultValue | ||
} | ||
if (typeof path === 'string') { | ||
return objectPath.get(obj, path.split('.'), defaultValue); | ||
return objectPath.get(obj, path.split('.'), defaultValue) | ||
} | ||
var currentPath = getKey(path[0]); | ||
var nextObj = getShallowProperty(obj, currentPath) | ||
var currentPath = getKey(path[0]) | ||
var nextObj = getShallowPropertySafely(obj, currentPath) | ||
if (nextObj === void 0) { | ||
return defaultValue; | ||
return defaultValue | ||
} | ||
if (path.length === 1) { | ||
return nextObj; | ||
return nextObj | ||
} | ||
return objectPath.get(obj[currentPath], path.slice(1), defaultValue); | ||
}; | ||
return objectPath.get(obj[currentPath], path.slice(1), defaultValue) | ||
} | ||
objectPath.del = function del(obj, path) { | ||
objectPath.del = function del (obj, path) { | ||
if (typeof path === 'number') { | ||
path = [path]; | ||
path = [path] | ||
} | ||
if (obj == null) { | ||
return obj; | ||
return obj | ||
} | ||
if (isEmpty(path)) { | ||
return obj; | ||
return obj | ||
} | ||
if(typeof path === 'string') { | ||
return objectPath.del(obj, path.split('.')); | ||
if (typeof path === 'string') { | ||
return objectPath.del(obj, path.split('.')) | ||
} | ||
var currentPath = getKey(path[0]); | ||
var currentPath = getKey(path[0]) | ||
getShallowPropertySafely(obj, currentPath) | ||
if (!hasShallowProperty(obj, currentPath)) { | ||
return obj; | ||
return obj | ||
} | ||
if(path.length === 1) { | ||
if (path.length === 1) { | ||
if (isArray(obj)) { | ||
obj.splice(currentPath, 1); | ||
obj.splice(currentPath, 1) | ||
} else { | ||
delete obj[currentPath]; | ||
delete obj[currentPath] | ||
} | ||
} else { | ||
return objectPath.del(obj[currentPath], path.slice(1)); | ||
return objectPath.del(obj[currentPath], path.slice(1)) | ||
} | ||
return obj; | ||
return obj | ||
} | ||
return objectPath; | ||
return objectPath | ||
} | ||
var mod = factory(); | ||
mod.create = factory; | ||
var mod = factory() | ||
mod.create = factory | ||
mod.withInheritedProps = factory({includeInheritedProps: true}) | ||
return mod; | ||
}); | ||
return mod | ||
}) |
{ | ||
"name": "object-path", | ||
"description": "Access deep object properties using a path", | ||
"version": "0.11.7", | ||
"version": "0.11.8", | ||
"author": { | ||
@@ -6,0 +6,0 @@ "name": "Mario Casciaro" |
@@ -16,2 +16,6 @@ | ||
### 0.11.8 | ||
* **SECURITY FIX**. Fix a prototype pollution vulnerability in the `del()`, `empty()`, `push()`, `insert()` functions when using the "inherited props" mode (e.g. when a new `object-path` instance is created with the `includeInheritedProps` option set to `true` or when using the `withInheritedProps` default instance. To help with preventing this type of vulnerability in the client code, also the `get()` function will now throw an exception if an object's magic properties are accessed. The vulnerability does not exist in the default instance exposed by object path (e.g `objectPath.del()`) if using version >= `0.11.0`. | ||
### 0.11.6 | ||
@@ -180,2 +184,4 @@ | ||
**NOTE**: For security reasons `object-path` will throw an exception when trying to access an object's magic properties (e.g. `__proto__`, `constructor`) when in "inherited props" mode. | ||
### Immutability | ||
@@ -182,0 +188,0 @@ |
295
test.js
@@ -136,2 +136,39 @@ 'use strict' | ||
}) | ||
it('[security] should not get magic properties in default mode', function () { | ||
expect(objectPath.get({}, '__proto__')).to.be.undefined | ||
expect(objectPath.get({}, [['__proto__']])).to.be.undefined | ||
function Clazz() {} | ||
Clazz.prototype.test = [] | ||
expect(objectPath.get(new Clazz(), '__proto__')).to.be.undefined | ||
expect(objectPath.get(new Clazz(), [['__proto__']])).to.be.undefined | ||
expect(objectPath.get(new Clazz(), ['constructor', 'prototype'])).to.be.undefined | ||
}) | ||
it('[security] should not get magic properties in inheritedProps mode', function () { | ||
expect(function() { | ||
objectPath.withInheritedProps.get({}, '__proto__') | ||
}).to.throw('For security reasons') | ||
expect(function() { | ||
objectPath.withInheritedProps.get({}, [['__proto__']]) | ||
}).to.throw('For security reasons') | ||
function Clazz() {} | ||
Clazz.prototype.test = 'original' | ||
expect(function() { | ||
objectPath.withInheritedProps.get(new Clazz(), '__proto__') | ||
}).to.throw('For security reasons') | ||
expect(function() { | ||
objectPath.withInheritedProps.get(new Clazz(), [['__proto__']]) | ||
}).to.throw('For security reasons') | ||
expect(function() { | ||
objectPath.withInheritedProps.get(new Clazz(), ['constructor', 'prototype']) | ||
}).to.throw('For security reasons') | ||
}) | ||
}) | ||
@@ -248,5 +285,11 @@ | ||
objectPath.set({}, ['__proto__'], {}) | ||
expect(Object.prototype.toString).to.be.a('function') | ||
function Clazz() {} | ||
Clazz.prototype.test = 'original' | ||
objectPath.set({}, ['__proto__'], {test: 'this is bad'}) | ||
expect(Clazz.prototype.test).to.be.equal('original') | ||
objectPath.set(new Clazz(), '__proto__.test', 'this is bad') | ||
@@ -263,5 +306,6 @@ expect(Clazz.prototype.test).to.be.equal('original') | ||
it('[security] should throw an exception if trying to set magic properties in inheritedProps mode', function () { | ||
expect(function() {objectPath.withInheritedProps.set({}, '__proto__.injected', 'this is bad')}) | ||
.to.throw('For security reasons') | ||
expect(Object.prototype.injected).to.be.undefined | ||
expect(function() { | ||
objectPath.withInheritedProps.set({}, '__proto__.injected', 'this is bad') | ||
expect(Object.prototype.injected).to.be.undefined | ||
}).to.throw('For security reasons') | ||
@@ -276,17 +320,21 @@ expect(function() { | ||
expect(function() {objectPath.withInheritedProps.set(new Clazz(), '__proto__.test', 'this is bad')}) | ||
.to.throw('For security reasons') | ||
expect(Clazz.prototype.test).to.be.equal('original') | ||
expect(function() { | ||
objectPath.withInheritedProps.set(new Clazz(), '__proto__.test', 'this is bad') | ||
expect(Clazz.prototype.test).to.be.equal('original') | ||
}).to.throw('For security reasons') | ||
expect(function() {objectPath.withInheritedProps.set(new Clazz(), 'constructor.prototype.test', 'this is bad')}) | ||
.to.throw('For security reasons') | ||
expect(Clazz.prototype.test).to.be.equal('original') | ||
expect(function() { | ||
objectPath.withInheritedProps.set(new Clazz(), 'constructor.prototype.test', 'this is bad') | ||
expect(Clazz.prototype.test).to.be.equal('original') | ||
}).to.throw('For security reasons') | ||
expect(function() {objectPath.withInheritedProps.set({}, 'constructor.prototype.injected', 'this is OK')}) | ||
.to.throw('For security reasons') | ||
expect(Object.prototype.injected).to.be.undefined | ||
expect(function() { | ||
objectPath.withInheritedProps.set({}, 'constructor.prototype.injected', 'this is OK') | ||
expect(Object.prototype.injected).to.be.undefined | ||
}).to.throw('For security reasons') | ||
expect(function() {objectPath.withInheritedProps.set({}, [['constructor'], 'prototype', 'injected'], 'this is bad')}) | ||
.to.throw('For security reasons') | ||
expect(Object.prototype.injected).to.be.undefined | ||
expect(function() { | ||
objectPath.withInheritedProps.set({}, [['constructor'], 'prototype', 'injected'], 'this is bad') | ||
expect(Object.prototype.injected).to.be.undefined | ||
}).to.throw('For security reasons') | ||
}) | ||
@@ -335,2 +383,35 @@ }) | ||
it('[security] should not push within prototype properties in default mode', function () { | ||
function Clazz() {} | ||
Clazz.prototype.test = [] | ||
objectPath.push(new Clazz(), '__proto__.test', 'pushed') | ||
expect(Clazz.prototype.test).to.be.deep.equal([]) | ||
objectPath.push(new Clazz(), [['__proto__'], 'test'], 'pushed') | ||
expect(Clazz.prototype.test).to.be.deep.equal([]) | ||
objectPath.push(new Clazz(), 'constructor.prototype.test', 'pushed') | ||
expect(Clazz.prototype.test).to.be.deep.equal([]) | ||
}) | ||
it('[security] should not push within prototype properties in inheritedProps mode', function () { | ||
function Clazz() {} | ||
Clazz.prototype.test = [] | ||
expect(function() { | ||
objectPath.withInheritedProps.push(new Clazz(), '__proto__.test', 'pushed') | ||
expect(Clazz.prototype.test).to.be.deep.equal([]) | ||
}).to.throw('For security reasons') | ||
expect(function() { | ||
objectPath.withInheritedProps.push(new Clazz(), [['__proto__'], 'test'], 'pushed') | ||
expect(Clazz.prototype.test).to.be.deep.equal([]) | ||
}).to.throw('For security reasons') | ||
expect(function() { | ||
objectPath.withInheritedProps.push(new Clazz(), 'constructor.prototype.test', 'pushed') | ||
expect(Clazz.prototype.test).to.be.deep.equal([]) | ||
}).to.throw('For security reasons') | ||
}) | ||
}) | ||
@@ -369,2 +450,63 @@ | ||
}) | ||
it('[security] should not set magic properties in default mode', function () { | ||
objectPath.ensureExists({}, '__proto__.injected', 'this is bad') | ||
expect(Object.prototype.injected).to.be.undefined | ||
objectPath.ensureExists({}, [['__proto__'], 'injected'], 'this is bad') | ||
expect(Object.prototype.injected).to.be.undefined | ||
objectPath.ensureExists({}, ['__proto__'], {}) | ||
expect(Object.prototype.toString).to.be.a('function') | ||
function Clazz() {} | ||
Clazz.prototype.test = 'original' | ||
objectPath.ensureExists({}, ['__proto__'], {test: 'this is bad'}) | ||
expect(Clazz.prototype.test).to.be.equal('original') | ||
objectPath.ensureExists(new Clazz(), '__proto__.test', 'this is bad') | ||
expect(Clazz.prototype.test).to.be.equal('original') | ||
objectPath.ensureExists(new Clazz(), [['__proto__'], 'test'], 'this is bad') | ||
expect(Clazz.prototype.test).to.be.equal('original') | ||
objectPath.ensureExists(new Clazz(), 'constructor.prototype.test', 'this is bad') | ||
expect(Clazz.prototype.test).to.be.equal('original') | ||
}) | ||
it('[security] should throw an exception if trying to set magic properties in inheritedProps mode', function () { | ||
expect(function() {objectPath.withInheritedProps.ensureExists({}, '__proto__.injected', 'this is bad')}) | ||
.to.throw('For security reasons') | ||
expect(Object.prototype.injected).to.be.undefined | ||
expect(function() { | ||
objectPath.withInheritedProps.ensureExists({}, [['__proto__'], 'injected'], 'this is bad') | ||
expect(Object.prototype.injected).to.be.undefined | ||
}).to.throw('For security reasons') | ||
function Clazz() {} | ||
Clazz.prototype.test = 'original' | ||
expect(function() { | ||
objectPath.withInheritedProps.ensureExists(new Clazz(), '__proto__.test', 'this is bad') | ||
expect(Clazz.prototype.test).to.be.equal('original') | ||
}).to.throw('For security reasons') | ||
expect(function() { | ||
objectPath.withInheritedProps.ensureExists(new Clazz(), 'constructor.prototype.test', 'this is bad') | ||
expect(Clazz.prototype.test).to.be.equal('original') | ||
}).to.throw('For security reasons') | ||
expect(function() { | ||
objectPath.withInheritedProps.ensureExists({}, 'constructor.prototype.injected', 'this is OK') | ||
expect(Object.prototype.injected).to.be.undefined | ||
}).to.throw('For security reasons') | ||
expect(function() { | ||
objectPath.withInheritedProps.ensureExists({}, [['constructor'], 'prototype', 'injected'], 'this is bad') | ||
expect(Object.prototype.injected).to.be.undefined | ||
}).to.throw('For security reasons') | ||
}) | ||
}) | ||
@@ -521,2 +663,36 @@ | ||
}) | ||
it('[security] should not empty prototype properties in default mode', function () { | ||
function Clazz() {} | ||
Clazz.prototype.test = 'original' | ||
objectPath.empty(new Clazz(), '__proto__') | ||
expect(Clazz.prototype.test).to.be.equal('original') | ||
objectPath.empty(new Clazz(), [['__proto__']]) | ||
expect(Clazz.prototype.test).to.be.equal('original') | ||
objectPath.empty(new Clazz(), 'constructor.prototype') | ||
expect(Clazz.prototype.test).to.be.equal('original') | ||
}) | ||
it('[security] should throw an exception if trying to delete prototype properties in inheritedProps mode', function () { | ||
function Clazz() {} | ||
Clazz.prototype.test = 'original' | ||
expect(function() { | ||
objectPath.withInheritedProps.empty(new Clazz(), '__proto__') | ||
expect(Clazz.prototype.test).to.be.equal('original') | ||
}).to.throw('For security reasons') | ||
expect(function() { | ||
objectPath.withInheritedProps.empty(new Clazz(), 'constructor.prototype') | ||
expect(Clazz.prototype.test).to.be.equal('original') | ||
}).to.throw('For security reasons') | ||
expect(function() { | ||
objectPath.withInheritedProps.empty({}, [['constructor'], 'prototype']) | ||
expect(Clazz.prototype.test).to.be.equal('original') | ||
}).to.throw('For security reasons') | ||
}) | ||
}) | ||
@@ -598,2 +774,52 @@ | ||
}) | ||
it('[security] should not delete prototype properties in default mode', function () { | ||
objectPath.del({}, '__proto__.valueOf') | ||
expect(Object.prototype.valueOf).to.be.a('function') | ||
objectPath.del({}, [['__proto__'], 'valueOf']) | ||
expect(Object.prototype.valueOf).to.be.a('function') | ||
function Clazz() {} | ||
Clazz.prototype.test = 'original' | ||
objectPath.del(new Clazz(), '__proto__.test') | ||
expect(Clazz.prototype.test).to.be.equal('original') | ||
objectPath.del(new Clazz(), [['__proto__'], 'test']) | ||
expect(Clazz.prototype.test).to.be.equal('original') | ||
objectPath.del(new Clazz(), 'constructor.prototype.test') | ||
expect(Clazz.prototype.test).to.be.equal('original') | ||
}) | ||
it('[security] should throw an exception if trying to delete prototype properties in inheritedProps mode', function () { | ||
expect(function() { | ||
objectPath.withInheritedProps.del({}, '__proto__.valueOf') | ||
expect(Object.prototype.valueOf).to.be.a('function') | ||
}).to.throw('For security reasons') | ||
expect(function() { | ||
objectPath.withInheritedProps.del({}, [['__proto__'], 'valueOf']) | ||
expect(Object.prototype.valueOf).to.be.a('function') | ||
}).to.throw('For security reasons') | ||
function Clazz() {} | ||
Clazz.prototype.test = 'original' | ||
expect(function() { | ||
objectPath.withInheritedProps.del(new Clazz(), '__proto__.test') | ||
expect(Clazz.prototype.test).to.be.equal('original') | ||
}).to.throw('For security reasons') | ||
expect(function() { | ||
objectPath.withInheritedProps.del(new Clazz(), 'constructor.prototype.test', 'this is bad') | ||
expect(Clazz.prototype.test).to.be.equal('original') | ||
}).to.throw('For security reasons') | ||
expect(function() { | ||
objectPath.withInheritedProps.del({}, [['constructor'], 'prototype', 'test']) | ||
expect(Clazz.prototype.test).to.be.equal('original') | ||
}).to.throw('For security reasons') | ||
}) | ||
}) | ||
@@ -641,2 +867,41 @@ | ||
}) | ||
it('[security] should not insert within prototype properties in default mode', function () { | ||
function Clazz() {} | ||
Clazz.prototype.test = [] | ||
objectPath.insert(new Clazz(), '__proto__.test', 'inserted', 0) | ||
expect(Clazz.prototype.test).to.be.deep.equal([]) | ||
objectPath.insert(new Clazz(), [['__proto__'], 'test'], 'inserted', 0) | ||
expect(Clazz.prototype.test).to.be.deep.equal([]) | ||
objectPath.insert(new Clazz(), 'constructor.prototype.test', 'inserted', 0) | ||
expect(Clazz.prototype.test).to.be.deep.equal([]) | ||
}) | ||
it('[security] should not insert within prototype properties in inheritedProps mode', function () { | ||
function Clazz() {} | ||
Clazz.prototype.test = [] | ||
expect(function() { | ||
objectPath.withInheritedProps.insert(new Clazz(), '__proto__.test', 'inserted', 0) | ||
expect(Clazz.prototype.test).to.be.deep.equal([]) | ||
}).to.throw('For security reasons') | ||
expect(function() { | ||
objectPath.withInheritedProps.insert(new Clazz(), [['__proto__'], 'test'], 'inserted', 0) | ||
expect(Clazz.prototype.test).to.be.deep.equal([]) | ||
}).to.throw('For security reasons') | ||
expect(function() { | ||
objectPath.withInheritedProps.insert(new Clazz(), 'constructor.prototype.test', 'inserted', 0) | ||
expect(Clazz.prototype.test).to.be.deep.equal([]) | ||
}).to.throw('For security reasons') | ||
expect(function() { | ||
objectPath.withInheritedProps.insert(new Clazz().constructor, 'prototype.test', 'inserted', 0) | ||
expect(Clazz.prototype.test).to.be.deep.equal([]) | ||
}).to.throw('For security reasons') | ||
}) | ||
}) | ||
@@ -643,0 +908,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
60943
10
1391
194