Vulnerability: Code Injection in node-rules node-rules including 3.0.0 and prior to 5.0.0 allows injection of arbitrary commands. The argument rules of function "fromJSON()" can be controlled by users without any sanitization.
Vulnerability ID: GHSA-f78f-353m-cf4j
CWE: CWE-94
Severity score: 9.8
Project: https://github.com/mithunsatheesh/node-rules
Published: 2021-12-10
File: lib/node-rules.js
Commit message: Remove fromJSON and toJSON from exposed APIs

Remove fromJSON and toJSON from exposed APIs in V5.0.0
Commit author: Mithun Satheesh

Vulnerable version (before fix):
         }         this.sync();     }     RuleEngine.prototype.toJSON = function() {         var rules = this.rules;         if (rules instanceof Array) {             rules = rules.map(function(rule) {                 rule.condition = rule.condition.toString();                 rule.consequence = rule.consequence.toString();                 return rule;             });         } else if (typeof(rules) != "undefined") {             rules.condition = rules.condition.toString();             rules.consequence = rules.consequence.toString();         }         return rules;     };     RuleEngine.prototype.fromJSON = function(rules) {         this.init();         if (typeof(rules) == "string") {             rules = JSON.parse(rules);         }         if (rules instanceof Array) {             rules = rules.map(function(rule) {                 rule.condition = eval("(" + rule.condition + ")");                 rule.consequence = eval("(" + rule.consequence + ")");                 return rule;             });         } else if (rules !== null && typeof(rules) == "object") {             rules.condition = eval("(" + rules.condition + ")");             rules.consequence = eval("(" + rules.consequence + ")");         }         this.register(rules);     };     module.exports = RuleEngine; }(module.exports));

Fixed version (after fix):
         }         this.sync();     }     module.exports = RuleEngine; }(module.exports));

Patch:
patch: @@ -128,36 +128,5 @@
         }
         this.sync();
     }
-    RuleEngine.prototype.toJSON = function() {
-        var rules = this.rules;
-        if (rules instanceof Array) {
-            rules = rules.map(function(rule) {
-                rule.condition = rule.condition.toString();
-                rule.consequence = rule.consequence.toString();
-                return rule;
-            });
-        } else if (typeof(rules) != "undefined") {
-            rules.condition = rules.condition.toString();
-            rules.consequence = rules.consequence.toString();
-        }
-        return rules;
-    };
-    RuleEngine.prototype.fromJSON = function(rules) {
-        this.init();
-        if (typeof(rules) == "string") {
-            rules = JSON.parse(rules);
-        }
-        if (rules instanceof Array) {
-            rules = rules.map(function(rule) {
-                rule.condition = eval("(" + rule.condition + ")");
-                rule.consequence = eval("(" + rule.consequence + ")");
-                return rule;
-            });
-        } else if (rules !== null && typeof(rules) == "object") {
-            rules.condition = eval("(" + rules.condition + ")");
-            rules.consequence = eval("(" + rules.consequence + ")");
-        }
-        this.register(rules);
-    };
     module.exports = RuleEngine;
 }(module.exports));
path: lib/node-rules.js