+
+
+ Passing untrusted inputs to a JavaScript interpreter like `Js2Py` can lead to arbitrary
+ code execution.
+
+
+
+ This vulnerability can be prevented either by preventing an untrusted user input to flow
+ to an eval_js
call. Or, the impact of this vulnerability can be
+ significantly reduced by disabling imports from the interepreted code (note that in a
+ comment the author of the library highlights that Js2Py is still insecure with this
+ option).
+
+
+ In the example below, the Javascript code being evaluated is controlled by the user and
+ hence leads to arbitrary code execution.
+
+ This can be fixed by disabling imports before evaluating the user passed buffer.
+
+
+
diff --git a/python/ql/src/experimental/Security/CWE-094/Js2Py.ql b/python/ql/src/experimental/Security/CWE-094/Js2Py.ql
new file mode 100644
index 000000000000..5dc160077873
--- /dev/null
+++ b/python/ql/src/experimental/Security/CWE-094/Js2Py.ql
@@ -0,0 +1,38 @@
+/**
+ * @name JavaScript code execution.
+ * @description Passing user supplied arguments to a Javascript to Python translation engine such as Js2Py can lead to remote code execution.
+ * @problem.severity error
+ * @security-severity 9.3
+ * @precision high
+ * @kind path-problem
+ * @id py/js2py-rce
+ * @tags security
+ * experimental
+ * external/cwe/cwe-94
+ */
+
+import python
+import semmle.python.ApiGraphs
+import semmle.python.dataflow.new.TaintTracking
+import semmle.python.dataflow.new.RemoteFlowSources
+import semmle.python.Concepts
+
+module Js2PyFlowConfig implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node node) { node instanceof RemoteFlowSource }
+
+ predicate isSink(DataFlow::Node node) {
+ API::moduleImport("js2py").getMember(["eval_js", "eval_js6", "EvalJs"]).getACall().getArg(_) =
+ node
+ }
+}
+
+module Js2PyFlow = TaintTracking::Global