CVE-2023-26135: Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution') (CWE-1321)
value: All versions of the package flatnest are vulnerable to Prototype Pollution via the nest() function in the flatnest/nest.js file.
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: 2023-06-30T05:15Z
Repository: https://github.com/brycebaril/node-flatnest
Language: JavaScript
Files changed: flatten.js, nest.js, seek.js, test/flatten.js, test/nest.js
Commit date: 2023-12-21 15:36:55 -0800
Commit message: Prevent prototype pollution reported in issue #4

Diff: diff --git a/flatten.js b/flatten.js
index 7e8fae9..adda492 100644
--- a/flatten.js
+++ b/flatten.js
@@ -1,5 +1,7 @@
+'use strict'
+
 module.exports = flatten
 
 function flatten(obj) {
   var flattened = {}
 
diff --git a/nest.js b/nest.js
index e145ff0..99ef43a 100644
--- a/nest.js
+++ b/nest.js
@@ -1,5 +1,7 @@
+'use strict'
+
 module.exports = nest
 
 var seek = require("./seek")
 
 var circular = /\[Circular \((.+)\)\]/
@@ -35,10 +37,12 @@ function insert(target, path, value) {
   var pathBits = path.split(nestedRe)
   var parent = target
   var len = pathBits.length
   for (var i = 0; i < len; i += 2) {
     var key = pathBits[i]
+    if (key === "__proto__") continue
+    if (key === "constructor" && typeof target[key] == "function") continue
     var type = pathBits[i + 1]
 
     if (type == null && key) parent[key] = value
     if (type == "." && parent[key] == null) parent[key] = {}
     if (type == "[" && parent[key] == null) parent[key] = []
diff --git a/seek.js b/seek.js
index 559a75d..ffe30b6 100644
--- a/seek.js
+++ b/seek.js
@@ -1,5 +1,7 @@
+'use strict'
+
 module.exports = seek
 
 var nestedRe = /(\.|\[)/
 var scrub = /]/g
 
diff --git a/test/flatten.js b/test/flatten.js
index d602121..ab1747c 100644
--- a/test/flatten.js
+++ b/test/flatten.js
@@ -1,5 +1,7 @@
+'use strict'
+
 var test = require("tape").test
 
 var flatten = require("../flatten")
 
 test("init", function (t) {
diff --git a/test/nest.js b/test/nest.js
index 1d3f0c4..3b20640 100644
--- a/test/nest.js
+++ b/test/nest.js
@@ -1,5 +1,7 @@
+'use strict'
+
 var test = require("tape").test
 
 var nest = require("../nest")
 
 test("init", function (t) {
@@ -137,5 +139,13 @@ test("nest empty", function (t) {
   var struct = {}
   var expect = {}
   t.deepEquals(nest(struct), expect, "empty object is still empty")
   t.end()
 })
+
+test("no prototype pollution", function (t) {
+  nest({'constructor.prototype.fail': true})
+  nest({'__proto__.bad': true})
+  t.false({}.fail, "constructor.prototype not polluted")
+  t.false({}.bad, "__proto__ not polluted")
+  t.end()
+})

Fixed code: 'use strict'

'use strict'

    if (key === "__proto__") continue
    if (key === "constructor" && typeof target[key] == "function") continue
'use strict'

'use strict'

'use strict'


test("no prototype pollution", function (t) {
  nest({'constructor.prototype.fail': true})
  nest({'__proto__.bad': true})
  t.false({}.fail, "constructor.prototype not polluted")
  t.false({}.bad, "__proto__ not polluted")
  t.end()
})