CVE-2021-23558: Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution') (CWE-1321)
value: The package bmoor before 0.10.1 are vulnerable to Prototype Pollution due to missing sanitization in set function. **Note:** This vulnerability derives from an incomplete fix in [CVE-2020-7736](https://security.snyk.io/vuln/SNYK-JS-BMOOR-598664)
CWE description: The product receives input from an upstream component that specifies attributes that are to be initialized or updated in an object, but it does not properly control modifications of attributes of the object prototype.
CVSS v3 base score: 9.8
Published: 2022-01-28T22:15Z
Repository: https://github.com/b-heilman/bmoor
Language: JavaScript
Files changed: package.json, src/core.js, src/core.spec.js
Commit date: 2022-01-24 22:54:42 -0500
Commit message: fix: bug with [__proto__]

Diff: diff --git a/package.json b/package.json
index b717a25..85c60f7 100644
--- a/package.json
+++ b/package.json
@@ -1,8 +1,8 @@
 {
   "name": "bmoor",
-  "version": "0.10.0",
+  "version": "0.10.1",
   "author": "Brian Heilman <das.ist.junk@gmail.com>",
   "description": "A basic foundation for other libraries, establishing useful patterbs, and letting them be more.",
   "license": "MIT",
   "repository": {
     "type": "git",
@@ -27,9 +27,10 @@
     "typescript": "^4.4.4",
     "yargs": "^15.3.1"
   },
   "scripts": {
     "lint": "node ./node_modules/eslint/bin/eslint ./src",
-    "test": "npm run prettier && mocha --recursive \"./src/**/*.spec.js\"",
-    "prettier": "npx prettier --write ./src && npm run lint"
+    "test": "mocha --recursive \"./src/**/*.spec.js\"",
+    "prettier": "npx prettier --write ./src",
+    "finalize": "npm run lint && npm run prettier && npm run test"
   }
 }
diff --git a/src/core.js b/src/core.js
index bcc9b47..cb58493 100644
--- a/src/core.js
+++ b/src/core.js
@@ -180,11 +180,11 @@ function set(root, space, value) {
 	space = parse(space);
 
 	val = space.pop();
 
 	for (i = 0, c = space.length; i < c; i++) {
-		nextSpace = space[i];
+		nextSpace = String(space[i]);
 
 		if (
 			nextSpace === '__proto__' ||
 			nextSpace === 'constructor' ||
 			nextSpace === 'prototype'
@@ -203,10 +203,12 @@ function set(root, space, value) {
 
 	return curSpace;
 }
 
 function _makeSetter(property, next) {
+	property = String(property);
+
 	if (
 		property === '__proto__' ||
 		property === 'constructor' ||
 		property === 'prototype'
 	) {
@@ -263,11 +265,11 @@ function get(root, path) {
 	}
 
 	space = parse(path);
 	if (space.length) {
 		for (i = 0, c = space.length; i < c; i++) {
-			nextSpace = space[i];
+			nextSpace = String(space[i]);
 
 			if (
 				nextSpace === '__proto__' ||
 				nextSpace === 'constructor' ||
 				nextSpace === 'prototype'
@@ -285,10 +287,12 @@ function get(root, path) {
 
 	return curSpace;
 }
 
 function _makeGetter(property, next) {
+	property = String(property);
+
 	if (
 		property === '__proto__' ||
 		property === 'constructor' ||
 		property === 'prototype'
 	) {
diff --git a/src/core.spec.js b/src/core.spec.js
index 514d67c..824d5a4 100644
--- a/src/core.spec.js
+++ b/src/core.spec.js
@@ -90,10 +90,18 @@ describe('Testing object setting/getting', function () {
 
 			bmoor.set(t, '__proto__.polluted', true);
 
 			expect(t.polluted).to.not.equal(true);
 		});
+
+		it('should not allow __proto__ when in array', function () {
+			var t = {};
+
+			bmoor.set(t, [['__proto__'], 'polluted'], 'polluted');
+
+			expect(t.polluted).to.not.equal('polluted');
+		});
 	});
 
 	describe('::makeSetter', function () {
 		it('should actually work', function () {
 			var t = {},

Vulnerable code:   "version": "0.10.0",
    "test": "npm run prettier && mocha --recursive \"./src/**/*.spec.js\"",
    "prettier": "npx prettier --write ./src && npm run lint"
		nextSpace = space[i];
			nextSpace = space[i];
Fixed code:   "version": "0.10.1",
    "test": "mocha --recursive \"./src/**/*.spec.js\"",
    "prettier": "npx prettier --write ./src",
    "finalize": "npm run lint && npm run prettier && npm run test"
		nextSpace = String(space[i]);
	property = String(property);

			nextSpace = String(space[i]);
	property = String(property);


		it('should not allow __proto__ when in array', function () {
			var t = {};

			bmoor.set(t, [['__proto__'], 'polluted'], 'polluted');

			expect(t.polluted).to.not.equal('polluted');
		});