VYPR
Critical severity9.8GHSA Advisory· Published May 8, 2026· Updated May 12, 2026

CVE-2026-41507

CVE-2026-41507

Description

math-codegen generates code from mathematical expressions. Prior to version 0.4.3, string literal content passed to cg.parse() is injected verbatim into a new Function() body without sanitization. This allows an attacker to execute arbitrary system commands when user-controlled input reaches the parser. Any application exposing a math evaluation endpoint where user input flows into cg.parse() is vulnerable to full RCE. This issue has been patched in version 0.4.3.

Affected products

1

Patches

1
4bb52d303068

fix: improve code generation safety

https://github.com/mauriciopoppe/math-codegenMauricio PoppeApr 9, 2026via nvd-ref
7 files changed · +28 6
  • lib/CodeGenerator.js+1 1 modified
    @@ -79,7 +79,7 @@ CodeGenerator.prototype.compile = function (namespace) {
         '    $$processScope(scope)',
         '    ' + code,
         '  },',
    -    "  code: '" + code + "'",
    +    '  code: ' + JSON.stringify(code),
         '}'
       ].join('\n')
     
    
  • lib/Interpreter.js+5 0 modified
    @@ -21,6 +21,11 @@ const Interpreter = function (owner, options) {
         rawCallExpressionElements: false,
         applyFactoryToScope: false
       }, options)
    +
    +  const factory = this.options.factory
    +  if (typeof factory !== 'string' || !/^[a-zA-Z_$][a-zA-Z0-9_$]*(\.[a-zA-Z_$][a-zA-Z0-9_$]*)*$/.test(factory)) {
    +    throw new Error('factory must be a valid JS property access path (e.g. "ns.factory")')
    +  }
     }
     
     extend(Interpreter.prototype, types)
    
  • lib/node/AssignmentNode.js+1 1 modified
    @@ -1,5 +1,5 @@
     'use strict'
     
     module.exports = function (node) {
    -  return 'scope["' + node.name + '"] = ' + this.next(node.expr)
    +  return 'scope[' + JSON.stringify(node.name) + '] = ' + this.next(node.expr)
     }
    
  • lib/node/ConstantNode.js+2 1 modified
    @@ -3,5 +3,6 @@ module.exports = function (node) {
       if (this.options.raw) {
         return node.value
       }
    -  return this.options.factory + '(' + node.value + ')'
    +  const value = node.valueType === 'string' ? JSON.stringify(node.value) : node.value
    +  return this.options.factory + '(' + value + ')'
     }
    
  • lib/node/FunctionNode.js+1 1 modified
    @@ -2,7 +2,7 @@
     const SymbolNode = require('mr-parser').nodeTypes.SymbolNode
     
     const functionProxy = function (node) {
    -  return '$$mathCodegen.functionProxy(' + this.next(new SymbolNode(node.name)) + ', "' + node.name + '")'
    +  return '$$mathCodegen.functionProxy(' + this.next(new SymbolNode(node.name)) + ', ' + JSON.stringify(node.name) + ')'
     }
     
     module.exports = function (node) {
    
  • lib/node/SymbolNode.js+1 1 modified
    @@ -2,5 +2,5 @@
     
     module.exports = function (node) {
       const id = node.name
    -  return '$$mathCodegen.getProperty("' + id + '", scope, ns)'
    +  return '$$mathCodegen.getProperty(' + JSON.stringify(id) + ', scope, ns)'
     }
    
  • package-lock.json+17 1 modified
    @@ -60,6 +60,7 @@
           "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.10.tgz",
           "integrity": "sha512-JQM6k6ENcBFKVtWvLavlvi/mPcpYZ3+R+2EySDEMSMbp7Mn4FexlbbJVrx2R7Ijhr01T8gyqrOaABWIOgxeUyw==",
           "dev": true,
    +      "peer": true,
           "dependencies": {
             "@ampproject/remapping": "^2.1.0",
             "@babel/code-frame": "^7.18.6",
    @@ -736,6 +737,7 @@
           "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz",
           "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==",
           "dev": true,
    +      "peer": true,
           "bin": {
             "acorn": "bin/acorn"
           },
    @@ -1061,6 +1063,7 @@
               "url": "https://tidelift.com/funding/github/npm/browserslist"
             }
           ],
    +      "peer": true,
           "dependencies": {
             "caniuse-lite": "^1.0.30001370",
             "electron-to-chromium": "^1.4.202",
    @@ -1748,6 +1751,7 @@
           "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.23.0.tgz",
           "integrity": "sha512-pBG/XOn0MsJcKcTRLr27S5HpzQo4kLr+HjLQIyK4EiCsijDl/TB+h5uEuJU6bQ8Edvwz1XWOjpaP2qgnXGpTcA==",
           "dev": true,
    +      "peer": true,
           "dependencies": {
             "@eslint/eslintrc": "^1.3.1",
             "@humanwhocodes/config-array": "^0.10.4",
    @@ -1942,6 +1946,7 @@
           "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz",
           "integrity": "sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==",
           "dev": true,
    +      "peer": true,
           "dependencies": {
             "array-includes": "^3.1.4",
             "array.prototype.flat": "^1.2.5",
    @@ -2008,6 +2013,7 @@
           "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.2.5.tgz",
           "integrity": "sha512-8+BYsqiyZfpu6NXmdLOXVUfk8IocpCjpd8nMRRH0A9ulrcemhb2VI9RSJMEy5udx++A/YcVPD11zT8hpFq368g==",
           "dev": true,
    +      "peer": true,
           "dependencies": {
             "builtins": "^5.0.1",
             "eslint-plugin-es": "^4.1.0",
    @@ -2060,6 +2066,7 @@
           "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.0.1.tgz",
           "integrity": "sha512-uM4Tgo5u3UWQiroOyDEsYcVMOo7re3zmno0IZmB5auxoaQNIceAbXEkSt8RNrKtaYehARHG06pYK6K1JhtP0Zw==",
           "dev": true,
    +      "peer": true,
           "engines": {
             "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
           },
    @@ -2072,6 +2079,7 @@
           "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.31.1.tgz",
           "integrity": "sha512-j4/2xWqt/R7AZzG8CakGHA6Xa/u7iR8Q3xCxY+AUghdT92bnIDOBEefV456OeH0QvBcroVc0eyvrrLSyQGYIfg==",
           "dev": true,
    +      "peer": true,
           "dependencies": {
             "array-includes": "^3.1.5",
             "array.prototype.flatmap": "^1.3.0",
    @@ -6251,6 +6259,7 @@
           "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.10.tgz",
           "integrity": "sha512-JQM6k6ENcBFKVtWvLavlvi/mPcpYZ3+R+2EySDEMSMbp7Mn4FexlbbJVrx2R7Ijhr01T8gyqrOaABWIOgxeUyw==",
           "dev": true,
    +      "peer": true,
           "requires": {
             "@ampproject/remapping": "^2.1.0",
             "@babel/code-frame": "^7.18.6",
    @@ -6779,7 +6788,8 @@
           "version": "8.8.0",
           "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz",
           "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==",
    -      "dev": true
    +      "dev": true,
    +      "peer": true
         },
         "acorn-jsx": {
           "version": "5.3.2",
    @@ -7024,6 +7034,7 @@
           "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz",
           "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==",
           "dev": true,
    +      "peer": true,
           "requires": {
             "caniuse-lite": "^1.0.30001370",
             "electron-to-chromium": "^1.4.202",
    @@ -7537,6 +7548,7 @@
           "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.23.0.tgz",
           "integrity": "sha512-pBG/XOn0MsJcKcTRLr27S5HpzQo4kLr+HjLQIyK4EiCsijDl/TB+h5uEuJU6bQ8Edvwz1XWOjpaP2qgnXGpTcA==",
           "dev": true,
    +      "peer": true,
           "requires": {
             "@eslint/eslintrc": "^1.3.1",
             "@humanwhocodes/config-array": "^0.10.4",
    @@ -7738,6 +7750,7 @@
           "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz",
           "integrity": "sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==",
           "dev": true,
    +      "peer": true,
           "requires": {
             "array-includes": "^3.1.4",
             "array.prototype.flat": "^1.2.5",
    @@ -7794,6 +7807,7 @@
           "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.2.5.tgz",
           "integrity": "sha512-8+BYsqiyZfpu6NXmdLOXVUfk8IocpCjpd8nMRRH0A9ulrcemhb2VI9RSJMEy5udx++A/YcVPD11zT8hpFq368g==",
           "dev": true,
    +      "peer": true,
           "requires": {
             "builtins": "^5.0.1",
             "eslint-plugin-es": "^4.1.0",
    @@ -7830,13 +7844,15 @@
           "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.0.1.tgz",
           "integrity": "sha512-uM4Tgo5u3UWQiroOyDEsYcVMOo7re3zmno0IZmB5auxoaQNIceAbXEkSt8RNrKtaYehARHG06pYK6K1JhtP0Zw==",
           "dev": true,
    +      "peer": true,
           "requires": {}
         },
         "eslint-plugin-react": {
           "version": "7.31.1",
           "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.31.1.tgz",
           "integrity": "sha512-j4/2xWqt/R7AZzG8CakGHA6Xa/u7iR8Q3xCxY+AUghdT92bnIDOBEefV456OeH0QvBcroVc0eyvrrLSyQGYIfg==",
           "dev": true,
    +      "peer": true,
           "requires": {
             "array-includes": "^3.1.5",
             "array.prototype.flatmap": "^1.3.0",
    

Vulnerability mechanics

AI mechanics synthesis has not run for this CVE yet.

References

5

News mentions

0

No linked articles in our index yet.