CVE-2021-23389: Improper Control of Generation of Code ('Code Injection') (CWE-94)
value: The package total.js before 3.4.9 are vulnerable to Arbitrary Code Execution via the U.set() and U.get() functions.
CWE description: The product constructs all or part of a code segment using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the syntax or behavior of the intended code segment.
CVSS v3 base score: 9.8
Published: 2021-07-12T16:15Z
Repository: https://github.com/totaljs/framework
Language: JavaScript
Files changed: changes.txt, utils.js
Commit date: 2021-06-04 11:39:41 +0200
Commit message: Fixed security issue in `U.set()` and `U.get()`.

Diff: diff --git a/changes.txt b/changes.txt
index 91ba893a5..ee56f2216 100755
--- a/changes.txt
+++ b/changes.txt
@@ -2,10 +2,11 @@
 
 - added HTML escaping for meta tags
 - added `insecure` flag into the `U.request()` method
 - added `RESTBuilder.insecure()` method
 - fixed security issue when parsing query arguments (reported by <https://github.com/fl4x>)
+- fixed security in `U.get()` and `U.set()` (reported by Agustin Gianni)
 
 ======= 3.4.8
 
 - fixed measuring dimension for `.gif` images
 - fixed potential remote code execution in `U.set()` founded by [Snyk](https://snyk.io/vuln)
diff --git a/utils.js b/utils.js
index eecdcbbd8..3cfd23eab 100755
--- a/utils.js
+++ b/utils.js
@@ -6615,16 +6615,20 @@ exports.parseTheme = function(value) {
 		return '';
 	value = value.substring(1, index);
 	return value === '?' ? CONF.default_theme : value;
 };
 
+
 exports.set = function(obj, path, value) {
 	var cachekey = 'S+' + path;
 
 	if (F.temporary.other[cachekey])
 		return F.temporary.other[cachekey](obj, value);
 
+	if ((/__proto__|constructor|prototype|eval|function|\*|\+|;|\s|\(|\)|!/).test(path))
+		return value;
+
 	var arr = parsepath(path);
 	var builder = [];
 
 	for (var i = 0; i < arr.length - 1; i++) {
 		var type = arr[i + 1] ? (REGISARR.test(arr[i + 1]) ? '[]' : '{}') : '{}';
@@ -6634,25 +6638,25 @@ exports.set = function(obj, path, value) {
 
 	var v = arr[arr.length - 1];
 	var ispush = v.lastIndexOf('[]') !== -1;
 	var a = builder.join(';') + ';var v=typeof(a)===\'function\'?a(U.get(b)):a;w' + (v[0] === '[' ? '' : '.') + (ispush ? v.replace(REGREPLACEARR, '.push(v)') : (v + '=v')) + ';return v';
 
-	if ((/__proto__|constructor|prototype|eval/).test(a))
-		throw new Error('Potential vulnerability');
-
 	var fn = new Function('w', 'a', 'b', a);
 	F.temporary.other[cachekey] = fn;
-	fn(obj, value, path);
+	return fn(obj, value, path);
 };
 
 exports.get = function(obj, path) {
 
 	var cachekey = 'G=' + path;
 
 	if (F.temporary.other[cachekey])
 		return F.temporary.other[cachekey](obj);
 
+	if ((/__proto__|constructor|prototype|eval|function|\*|\+|;|\s|\(|\)|!/).test(path))
+		return;
+
 	var arr = parsepath(path);
 	var builder = [];
 
 	for (var i = 0, length = arr.length - 1; i < length; i++)
 		builder.push('if(!w' + (!arr[i] || arr[i][0] === '[' ? '' : '.') + arr[i] + ')return');

Vulnerable code: 	if ((/__proto__|constructor|prototype|eval/).test(a))
		throw new Error('Potential vulnerability');

	fn(obj, value, path);
Fixed code: - fixed security in `U.get()` and `U.set()` (reported by Agustin Gianni)

	if ((/__proto__|constructor|prototype|eval|function|\*|\+|;|\s|\(|\)|!/).test(path))
		return value;

	return fn(obj, value, path);
	if ((/__proto__|constructor|prototype|eval|function|\*|\+|;|\s|\(|\)|!/).test(path))
		return;