CVE-2023-45133: Incorrect Comparison (CWE-697)
value: Babel is a compiler for writingJavaScript. In `@babel/traverse` prior to versions 7.23.2 and 8.0.0-alpha.4 and all versions of `babel-traverse`, using Babel to compile code that was specifically crafted by an attacker can lead to arbitrary code execution during compilation, when using plugins that rely on the `path.evaluate()`or `path.evaluateTruthy()` internal Babel methods. Known affected plugins are `@babel/plugin-transform-runtime`; `@babel/preset-env` when using its `useBuiltIns` option; and any "polyfill provider" plugin that depends on `@babel/helper-define-polyfill-provider`, such as `babel-plugin-polyfill-corejs3`, `babel-plugin-polyfill-corejs2`, `babel-plugin-polyfill-es-shims`, `babel-plugin-polyfill-regenerator`. No other plugins under the `@babel/` namespace are impacted, but third-party plugins might be. Users that only compile trusted code are not impacted. The vulnerability has been fixed in `@babel/traverse@7.23.2` and `@babel/traverse@8.0.0-alpha.4`. Those who cannot upgrade `@babel/traverse` and are using one of the affected packages mentioned above should upgrade them to their latest version to avoid triggering the vulnerable code path in affected `@babel/traverse` versions: `@babel/plugin-transform-runtime` v7.23.2, `@babel/preset-env` v7.23.2, `@babel/helper-define-polyfill-provider` v0.4.3, `babel-plugin-polyfill-corejs2` v0.4.6, `babel-plugin-polyfill-corejs3` v0.8.5, `babel-plugin-polyfill-es-shims` v0.10.0, `babel-plugin-polyfill-regenerator` v0.5.3.
CWE description: The product compares two entities in a security-relevant context, but the comparison is incorrect, which may lead to resultant weaknesses.
CVSS v3 base score: 8.8
Published: 2023-10-12T17:15Z
Repository: https://github.com/babel/babel
Language: JavaScript
Files changed: packages/babel-traverse/src/path/evaluation.ts, packages/babel-traverse/test/evaluation.js
Commit date: 2023-10-11 11:54:14 -0400
Commit message: Only evaluate own String/Number/Math methods (#16033)


Diff: diff --git a/packages/babel-traverse/src/path/evaluation.ts b/packages/babel-traverse/src/path/evaluation.ts
index 9223dfebfc..2f83861822 100644
--- a/packages/babel-traverse/src/path/evaluation.ts
+++ b/packages/babel-traverse/src/path/evaluation.ts
@@ -442,12 +442,15 @@ function _evaluate(path: NodePath, state: State): any {
         property.isIdentifier() &&
         isValidObjectCallee(object.node.name) &&
         !isInvalidMethod(property.node.name)
       ) {
         context = global[object.node.name];
-        // @ts-expect-error property may not exist in context object
-        func = context[property.node.name];
+        const key = property.node.name;
+        // TODO(Babel 8): Use Object.hasOwn
+        if (Object.hasOwnProperty.call(context, key)) {
+          func = context[key as keyof typeof context];
+        }
       }
 
       // "abc".charCodeAt(4)
       if (object.isLiteral() && property.isIdentifier()) {
         // @ts-expect-error todo(flow->ts): consider checking ast node type instead of value type (StringLiteral and NumberLiteral)
diff --git a/packages/babel-traverse/test/evaluation.js b/packages/babel-traverse/test/evaluation.js
index c30f32f2a0..2d109eb1de 100644
--- a/packages/babel-traverse/test/evaluation.js
+++ b/packages/babel-traverse/test/evaluation.js
@@ -150,10 +150,16 @@ describe("evaluation", function () {
       .evaluate();
     expect(eval_member_expr.value).toBe(2);
     expect(eval_invalid_call.confident).toBe(false);
   });
 
+  it("should not evaluate inherited methods", function () {
+    const path = getPath("Math.hasOwnProperty('min')");
+    const evalResult = path.get("body.0.expression").evaluate();
+    expect(evalResult.confident).toBe(false);
+  });
+
   it("should evaluate global call expressions", function () {
     expect(
       getPath("isFinite(1);").get("body.0.expression").evaluate().value,
     ).toBe(true);
 

Vulnerable code:         // @ts-expect-error property may not exist in context object
        func = context[property.node.name];
Fixed code:         const key = property.node.name;
        // TODO(Babel 8): Use Object.hasOwn
        if (Object.hasOwnProperty.call(context, key)) {
          func = context[key as keyof typeof context];
        }
  it("should not evaluate inherited methods", function () {
    const path = getPath("Math.hasOwnProperty('min')");
    const evalResult = path.get("body.0.expression").evaluate();
    expect(evalResult.confident).toBe(false);
  });