Package: release.debian.org
Severity: normal
Tags: bullseye
User: release.debian....@packages.debian.org
Usertags: pu

[ Reason ]
node-object-path is vulnerable to prototye pollution (CVE-2021-23434 and
CVE-2021-3805

[ Impact ]
Medium vulnerability

[ Tests ]
Test passed with these patches, including new checks

[ Risks ]
Low risk, package is not really different than the one pushed to
unstable (only doc differs).

[ Checklist ]
  [X] *all* changes are documented in the d/changelog
  [X] I reviewed all changes and I approve them
  [X] attach debdiff against the package in (old)stable
  [X] the issue is verified as fixed in unstable

[ Changes ]
Better checks

[ Other info ]
Note that we could upload a 0.11.8-1~deb11u1: there is no differences
except a documentation update. If you agree, I prefer this way.

Cheers,
Yadd
diff --git a/debian/changelog b/debian/changelog
index f1e6929..ce9339e 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,11 @@
+node-object-path (0.11.5-3+deb11u1) bullseye; urgency=medium
+
+  * Team upload
+  * Fix prototype pollution (Closes: CVE-2021-23434)
+  * Fix prototype pollution (Closes: CVE-2021-3805)
+
+ -- Yadd <y...@debian.org>  Fri, 17 Sep 2021 18:38:10 +0200
+
 node-object-path (0.11.5-3) unstable; urgency=medium
 
   * Team upload
diff --git a/debian/gbp.conf b/debian/gbp.conf
index b713356..e11bcb5 100644
--- a/debian/gbp.conf
+++ b/debian/gbp.conf
@@ -1,5 +1,6 @@
 [DEFAULT]
 pristine-tar = True
+debian-branch = bullseye
 
 [import-orig]
 filter = [ '.gitignore', '.travis.yml', '.git*' ]
diff --git a/debian/patches/CVE-2021-23434.patch 
b/debian/patches/CVE-2021-23434.patch
new file mode 100644
index 0000000..8d08d2e
--- /dev/null
+++ b/debian/patches/CVE-2021-23434.patch
@@ -0,0 +1,67 @@
+Description: Fix prototype pollution when path components are not strings
+Author: Mario Casciaro <mariocasci...@gmail.com
+Origin: upstream, https://github.com/mariocasciaro/object-path/commit/7bdf4abef
+Bug: https://snyk.io/vuln/SNYK-JS-OBJECTPATH-1569453
+Forwarded: not-needed
+Reviewed-By: Yadd <y...@debian.org>
+Last-Update: 2021-09-17
+
+--- a/index.js
++++ b/index.js
+@@ -111,6 +111,9 @@
+         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'))) {
+--- a/test.js
++++ b/test.js
+@@ -241,12 +241,18 @@
+     objectPath.set({}, '__proto__.injected', 'this is bad')
+     expect(Object.prototype.injected).to.be.undefined
+ 
++    objectPath.set({}, [['__proto__'], 'injected'], 'this is bad')
++    expect(Object.prototype.injected).to.be.undefined
++
+     function Clazz() {}
+     Clazz.prototype.test = 'original'
+ 
+     objectPath.set(new Clazz(), '__proto__.test', 'this is bad')
+     expect(Clazz.prototype.test).to.be.equal('original')
+ 
++    objectPath.set(new Clazz(), [['__proto__'], 'test'], 'this is bad')
++    expect(Clazz.prototype.test).to.be.equal('original')
++
+     objectPath.set(new Clazz(), 'constructor.prototype.test', 'this is bad')
+     expect(Clazz.prototype.test).to.be.equal('original')
+   })
+@@ -256,6 +262,11 @@
+       .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')
++
+     function Clazz() {}
+     Clazz.prototype.test = 'original'
+ 
+@@ -267,8 +278,11 @@
+       .to.throw('For security reasons')
+     expect(Clazz.prototype.test).to.be.equal('original')
+ 
+-    const obj = {}
+-    expect(function() {objectPath.withInheritedProps.set(obj, 
'constructor.prototype.injected', 'this is OK')})
++    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 bad')})
+       .to.throw('For security reasons')
+     expect(Object.prototype.injected).to.be.undefined
+   })
diff --git a/debian/patches/CVE-2021-3805.patch 
b/debian/patches/CVE-2021-3805.patch
new file mode 100644
index 0000000..daa56ff
--- /dev/null
+++ b/debian/patches/CVE-2021-3805.patch
@@ -0,0 +1,837 @@
+Description: Fix prototype pollution vulnerability
+Author: Mario Casciaro <mariocasci...@gmail.com>
+Origin: upstream, https://github.com/mariocasciaro/object-path/commit/4f0903fd7
+Bug: https://huntr.dev/bounties/571e3baf-7c46-46e3-9003-ba7e4e623053
+Forwarded: not-needed
+Reviewed-By: Yadd <y...@debian.org>
+Last-Update: 2021-09-17
+
+--- a/README.md
++++ b/README.md
+@@ -172,6 +172,8 @@
+ objectPath.set(obj, 'notOwn.prop', 'b');
+ ```
+ 
++**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
+ 
+ If you are looking for an *immutable* alternative of this library, you can 
take a look at: 
[object-path-immutable](https://github.com/mariocasciaro/object-path-immutable)
+--- a/index.js
++++ b/index.js
+@@ -1,87 +1,88 @@
+-(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
+     }
+     //to handle objects with null prototypes (too edge case?)
+     return Object.prototype.hasOwnProperty.call(obj, prop)
+   }
+ 
+-  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
+         }
+ 
+         /*istanbul ignore else*/
+         if (typeof objectPath[prop] === 'function') {
+-          proxy[prop] = objectPath[prop].bind(objectPath, obj);
++          proxy[prop] = objectPath[prop].bind(objectPath, obj)
+         }
+ 
+-        return proxy;
+-      }, {});
+-    };
++        return proxy
++      }, {})
++    }
+ 
+     var hasShallowProperty
+     if (options.includeInheritedProps) {
+@@ -94,213 +95,226 @@
+       }
+     }
+ 
+-    function getShallowProperty(obj, prop) {
++    function getShallowProperty (obj, prop) {
+       if (hasShallowProperty(obj, prop)) {
+-        return obj[prop];
++        return obj[prop]
++      }
++    }
++
++    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){
++    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);
+-      }
+-      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')
++        return set(obj, path.split('.').map(getKey), value, doNotReplace)
+       }
++      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
+       }
+ 
+       if (currentValue === void 0) {
+         //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)
+     }
+ 
+     objectPath.has = function (obj, path) {
+       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
++})
+--- a/test.js
++++ b/test.js
+@@ -133,6 +133,43 @@
+     expect(objectPath.get(extended, 'enabled')).to.be.equal(true)
+     expect(objectPath.get(extended, 'one')).to.be.equal(undefined)
+   })
++
++  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')
++  })
+ })
+ 
+ 
+@@ -244,9 +281,15 @@
+     objectPath.set({}, [['__proto__'], 'injected'], 'this is bad')
+     expect(Object.prototype.injected).to.be.undefined
+ 
++    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')
+     expect(Clazz.prototype.test).to.be.equal('original')
+ 
+@@ -258,9 +301,10 @@
+   })
+ 
+   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')
+ 
+     expect(function() {
+       objectPath.withInheritedProps.set({}, [['__proto__'], 'injected'], 
'this is bad')
+@@ -270,21 +314,25 @@
+     function Clazz() {}
+     Clazz.prototype.test = 'original'
+ 
+-    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')
+   })
+ })
+ 
+@@ -328,6 +376,39 @@
+     expect(obj).to.have.nested.property('b.e.0.0', 'l')
+   })
+ 
++  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')
++  })
+ })
+ 
+ 
+@@ -361,6 +442,67 @@
+     expect(any[1]).to.be.an('object')
+     expect(any[1][1]).to.be.an('object')
+   })
++
++  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')
++  })
+ })
+ 
+ describe('coalesce', function () {
+@@ -512,6 +654,40 @@
+     expect(obj.instance.arr).to.be.an('array')
+     expect(obj['function']).to.equal(null)
+   })
++
++  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')
++  })
+ })
+ 
+ describe('del', function () {
+@@ -588,6 +764,56 @@
+     expect(obj.b.d).to.have.length(0)
+     expect(obj.b.d).to.be.deep.equal([])
+   })
++
++  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')
++  })
+ })
+ 
+ describe('insert', function () {
+@@ -630,6 +856,45 @@
+       'asdf'
+     ])
+   })
++
++  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')
++  })
+ })
+ 
+ describe('has', function () {
diff --git a/debian/patches/series b/debian/patches/series
new file mode 100644
index 0000000..7b1f359
--- /dev/null
+++ b/debian/patches/series
@@ -0,0 +1,2 @@
+CVE-2021-23434.patch
+CVE-2021-3805.patch
diff --git a/debian/salsa-ci.yml b/debian/salsa-ci.yml
index 33c3a64..6fd902a 100644
--- a/debian/salsa-ci.yml
+++ b/debian/salsa-ci.yml
@@ -1,4 +1,7 @@
 ---
+variables:
+  RELEASE: 'bullseye'
+
 include:
   - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/salsa-ci.yml
   - 
https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/pipeline-jobs.yml

Reply via email to