diff --git a/javascript/ql/lib/change-notes/2023-06-22-webix.md b/javascript/ql/lib/change-notes/2023-06-22-webix.md
new file mode 100644
index 000000000000..9daa1b1a5dcc
--- /dev/null
+++ b/javascript/ql/lib/change-notes/2023-06-22-webix.md
@@ -0,0 +1,4 @@
+---
+category: minorAnalysis
+---
+* Added models for the Webix Framework.
\ No newline at end of file
diff --git a/javascript/ql/lib/javascript.qll b/javascript/ql/lib/javascript.qll
index ed38db6550e2..07fb759bd655 100644
--- a/javascript/ql/lib/javascript.qll
+++ b/javascript/ql/lib/javascript.qll
@@ -134,6 +134,7 @@ import semmle.javascript.frameworks.TrustedTypes
import semmle.javascript.frameworks.UriLibraries
import semmle.javascript.frameworks.Vue
import semmle.javascript.frameworks.Vuex
+import semmle.javascript.frameworks.Webix
import semmle.javascript.frameworks.WebSocket
import semmle.javascript.frameworks.XmlParsers
import semmle.javascript.frameworks.xUnit
diff --git a/javascript/ql/lib/semmle/javascript/Extend.qll b/javascript/ql/lib/semmle/javascript/Extend.qll
index 3b389691434f..d0eeade58928 100644
--- a/javascript/ql/lib/semmle/javascript/Extend.qll
+++ b/javascript/ql/lib/semmle/javascript/Extend.qll
@@ -96,7 +96,10 @@ private class ExtendCallDeep extends ExtendCall {
callee = LodashUnderscore::member("merge") or
callee = LodashUnderscore::member("mergeWith") or
callee = LodashUnderscore::member("defaultsDeep") or
- callee = AngularJS::angular().getAPropertyRead("merge")
+ callee = AngularJS::angular().getAPropertyRead("merge") or
+ callee =
+ [DataFlow::moduleImport("webix"), DataFlow::globalVarRef("webix")]
+ .getAPropertyRead(["extend", "copy"])
)
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Webix.qll b/javascript/ql/lib/semmle/javascript/frameworks/Webix.qll
new file mode 100644
index 000000000000..effd49c632bf
--- /dev/null
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Webix.qll
@@ -0,0 +1,23 @@
+/**
+ * Provides classes and predicates for working with the `webix` library.
+ */
+
+private import javascript
+
+/**
+ * Provides classes and predicates for working with the `webix` library.
+ */
+module Webix {
+ /** The global variable `webix` as an entry point for API graphs. */
+ private class WebixGlobalEntry extends API::EntryPoint {
+ WebixGlobalEntry() { this = "WebixGlobalEntry" }
+
+ override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef("webix") }
+ }
+
+ /** Gets a reference to the Webix package. */
+ API::Node webix() {
+ result = API::moduleImport("webix") or
+ result = any(WebixGlobalEntry w).getANode()
+ }
+}
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll
index 5d658b23b592..ce05747ec3f2 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll
@@ -312,6 +312,13 @@ module CodeInjection {
}
}
+ /**
+ * A value interpreted as code by the `webix` library.
+ */
+ class WebixExec extends Sink {
+ WebixExec() { this = Webix::webix().getMember("exec").getParameter(0).asSink() }
+ }
+
/** A sink for code injection via template injection. */
abstract private class TemplateSink extends Sink {
deprecated override string getMessageSuffix() {
@@ -419,6 +426,18 @@ module CodeInjection {
}
}
+ /**
+ * A value interpreted as a template by the `webix` library.
+ */
+ class WebixTemplateSink extends TemplateSink {
+ WebixTemplateSink() {
+ this = Webix::webix().getMember("ui").getParameter(0).getMember("template").asSink()
+ or
+ this =
+ Webix::webix().getMember("ui").getParameter(0).getMember("template").getReturn().asSink()
+ }
+ }
+
/**
* A call to JSON.stringify() seen as a sanitizer.
*/
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionCustomizations.qll
index bd233e33ae1d..fdd1b5c1c881 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionCustomizations.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionCustomizations.qll
@@ -171,5 +171,9 @@ module PrototypePollution {
call.isDeep() and
call = AngularJS::angular().getAMemberCall("merge") and
id = "angular"
+ or
+ call.isDeep() and
+ call = Webix::webix().getMember(["extend", "copy"]).getACall() and
+ id = "webix"
}
}
diff --git a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected
index d866329402a8..1193c5e33bce 100644
--- a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected
@@ -112,37 +112,37 @@ nodes
| react.js:10:56:10:77 | documen ... on.hash |
| react.js:10:56:10:77 | documen ... on.hash |
| react.js:10:56:10:77 | documen ... on.hash |
-| template-sinks.js:17:9:17:31 | tainted |
-| template-sinks.js:17:19:17:31 | req.query.foo |
-| template-sinks.js:17:19:17:31 | req.query.foo |
-| template-sinks.js:19:17:19:23 | tainted |
-| template-sinks.js:19:17:19:23 | tainted |
-| template-sinks.js:20:16:20:22 | tainted |
-| template-sinks.js:20:16:20:22 | tainted |
-| template-sinks.js:21:18:21:24 | tainted |
-| template-sinks.js:21:18:21:24 | tainted |
-| template-sinks.js:22:17:22:23 | tainted |
-| template-sinks.js:22:17:22:23 | tainted |
-| template-sinks.js:23:18:23:24 | tainted |
-| template-sinks.js:23:18:23:24 | tainted |
-| template-sinks.js:24:16:24:22 | tainted |
-| template-sinks.js:24:16:24:22 | tainted |
-| template-sinks.js:25:27:25:33 | tainted |
-| template-sinks.js:25:27:25:33 | tainted |
-| template-sinks.js:26:21:26:27 | tainted |
-| template-sinks.js:26:21:26:27 | tainted |
-| template-sinks.js:27:17:27:23 | tainted |
-| template-sinks.js:27:17:27:23 | tainted |
-| template-sinks.js:28:24:28:30 | tainted |
-| template-sinks.js:28:24:28:30 | tainted |
-| template-sinks.js:29:21:29:27 | tainted |
-| template-sinks.js:29:21:29:27 | tainted |
-| template-sinks.js:30:19:30:25 | tainted |
-| template-sinks.js:30:19:30:25 | tainted |
-| template-sinks.js:31:16:31:22 | tainted |
-| template-sinks.js:31:16:31:22 | tainted |
-| template-sinks.js:32:17:32:23 | tainted |
-| template-sinks.js:32:17:32:23 | tainted |
+| template-sinks.js:18:9:18:31 | tainted |
+| template-sinks.js:18:19:18:31 | req.query.foo |
+| template-sinks.js:18:19:18:31 | req.query.foo |
+| template-sinks.js:20:17:20:23 | tainted |
+| template-sinks.js:20:17:20:23 | tainted |
+| template-sinks.js:21:16:21:22 | tainted |
+| template-sinks.js:21:16:21:22 | tainted |
+| template-sinks.js:22:18:22:24 | tainted |
+| template-sinks.js:22:18:22:24 | tainted |
+| template-sinks.js:23:17:23:23 | tainted |
+| template-sinks.js:23:17:23:23 | tainted |
+| template-sinks.js:24:18:24:24 | tainted |
+| template-sinks.js:24:18:24:24 | tainted |
+| template-sinks.js:25:16:25:22 | tainted |
+| template-sinks.js:25:16:25:22 | tainted |
+| template-sinks.js:26:27:26:33 | tainted |
+| template-sinks.js:26:27:26:33 | tainted |
+| template-sinks.js:27:21:27:27 | tainted |
+| template-sinks.js:27:21:27:27 | tainted |
+| template-sinks.js:28:17:28:23 | tainted |
+| template-sinks.js:28:17:28:23 | tainted |
+| template-sinks.js:29:24:29:30 | tainted |
+| template-sinks.js:29:24:29:30 | tainted |
+| template-sinks.js:30:21:30:27 | tainted |
+| template-sinks.js:30:21:30:27 | tainted |
+| template-sinks.js:31:19:31:25 | tainted |
+| template-sinks.js:31:19:31:25 | tainted |
+| template-sinks.js:32:16:32:22 | tainted |
+| template-sinks.js:32:16:32:22 | tainted |
+| template-sinks.js:33:17:33:23 | tainted |
+| template-sinks.js:33:17:33:23 | tainted |
| tst.js:2:6:2:27 | documen ... on.href |
| tst.js:2:6:2:27 | documen ... on.href |
| tst.js:2:6:2:83 | documen ... t=")+8) |
@@ -181,6 +181,24 @@ nodes
| tst.js:35:28:35:33 | source |
| tst.js:37:33:37:38 | source |
| tst.js:37:33:37:38 | source |
+| webix/webix.html:3:16:3:37 | documen ... on.hash |
+| webix/webix.html:3:16:3:37 | documen ... on.hash |
+| webix/webix.html:3:16:3:37 | documen ... on.hash |
+| webix/webix.html:4:26:4:47 | documen ... on.hash |
+| webix/webix.html:4:26:4:47 | documen ... on.hash |
+| webix/webix.html:4:26:4:47 | documen ... on.hash |
+| webix/webix.html:5:47:5:68 | documen ... on.hash |
+| webix/webix.html:5:47:5:68 | documen ... on.hash |
+| webix/webix.html:5:47:5:68 | documen ... on.hash |
+| webix/webix.js:3:12:3:33 | documen ... on.hash |
+| webix/webix.js:3:12:3:33 | documen ... on.hash |
+| webix/webix.js:3:12:3:33 | documen ... on.hash |
+| webix/webix.js:4:22:4:43 | documen ... on.hash |
+| webix/webix.js:4:22:4:43 | documen ... on.hash |
+| webix/webix.js:4:22:4:43 | documen ... on.hash |
+| webix/webix.js:5:43:5:64 | documen ... on.hash |
+| webix/webix.js:5:43:5:64 | documen ... on.hash |
+| webix/webix.js:5:43:5:64 | documen ... on.hash |
edges
| NoSQLCodeInjection.js:18:24:18:31 | req.body | NoSQLCodeInjection.js:18:24:18:37 | req.body.query |
| NoSQLCodeInjection.js:18:24:18:31 | req.body | NoSQLCodeInjection.js:18:24:18:37 | req.body.query |
@@ -246,36 +264,36 @@ edges
| react-native.js:7:17:7:33 | req.param("code") | react-native.js:7:7:7:33 | tainted |
| react-native.js:7:17:7:33 | req.param("code") | react-native.js:7:7:7:33 | tainted |
| react.js:10:56:10:77 | documen ... on.hash | react.js:10:56:10:77 | documen ... on.hash |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:19:17:19:23 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:19:17:19:23 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:20:16:20:22 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:20:16:20:22 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:21:18:21:24 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:21:18:21:24 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:22:17:22:23 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:22:17:22:23 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:23:18:23:24 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:23:18:23:24 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:24:16:24:22 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:24:16:24:22 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:25:27:25:33 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:25:27:25:33 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:26:21:26:27 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:26:21:26:27 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:27:17:27:23 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:27:17:27:23 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:28:24:28:30 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:28:24:28:30 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:29:21:29:27 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:29:21:29:27 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:30:19:30:25 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:30:19:30:25 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:31:16:31:22 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:31:16:31:22 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:32:17:32:23 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:32:17:32:23 | tainted |
-| template-sinks.js:17:19:17:31 | req.query.foo | template-sinks.js:17:9:17:31 | tainted |
-| template-sinks.js:17:19:17:31 | req.query.foo | template-sinks.js:17:9:17:31 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:20:17:20:23 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:20:17:20:23 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:21:16:21:22 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:21:16:21:22 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:22:18:22:24 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:22:18:22:24 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:23:17:23:23 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:23:17:23:23 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:24:18:24:24 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:24:18:24:24 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:25:16:25:22 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:25:16:25:22 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:26:27:26:33 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:26:27:26:33 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:27:21:27:27 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:27:21:27:27 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:28:17:28:23 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:28:17:28:23 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:29:24:29:30 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:29:24:29:30 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:30:21:30:27 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:30:21:30:27 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:31:19:31:25 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:31:19:31:25 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:32:16:32:22 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:32:16:32:22 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:33:17:33:23 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:33:17:33:23 | tainted |
+| template-sinks.js:18:19:18:31 | req.query.foo | template-sinks.js:18:9:18:31 | tainted |
+| template-sinks.js:18:19:18:31 | req.query.foo | template-sinks.js:18:9:18:31 | tainted |
| tst.js:2:6:2:27 | documen ... on.href | tst.js:2:6:2:83 | documen ... t=")+8) |
| tst.js:2:6:2:27 | documen ... on.href | tst.js:2:6:2:83 | documen ... t=")+8) |
| tst.js:2:6:2:27 | documen ... on.href | tst.js:2:6:2:83 | documen ... t=")+8) |
@@ -306,6 +324,12 @@ edges
| tst.js:29:18:29:41 | documen ... .search | tst.js:29:18:29:82 | documen ... , "$1") |
| tst.js:29:18:29:41 | documen ... .search | tst.js:29:18:29:82 | documen ... , "$1") |
| tst.js:29:18:29:82 | documen ... , "$1") | tst.js:29:9:29:82 | source |
+| webix/webix.html:3:16:3:37 | documen ... on.hash | webix/webix.html:3:16:3:37 | documen ... on.hash |
+| webix/webix.html:4:26:4:47 | documen ... on.hash | webix/webix.html:4:26:4:47 | documen ... on.hash |
+| webix/webix.html:5:47:5:68 | documen ... on.hash | webix/webix.html:5:47:5:68 | documen ... on.hash |
+| webix/webix.js:3:12:3:33 | documen ... on.hash | webix/webix.js:3:12:3:33 | documen ... on.hash |
+| webix/webix.js:4:22:4:43 | documen ... on.hash | webix/webix.js:4:22:4:43 | documen ... on.hash |
+| webix/webix.js:5:43:5:64 | documen ... on.hash | webix/webix.js:5:43:5:64 | documen ... on.hash |
#select
| NoSQLCodeInjection.js:18:24:18:37 | req.body.query | NoSQLCodeInjection.js:18:24:18:31 | req.body | NoSQLCodeInjection.js:18:24:18:37 | req.body.query | This code execution depends on a $@. | NoSQLCodeInjection.js:18:24:18:31 | req.body | user-provided value |
| NoSQLCodeInjection.js:19:24:19:48 | "name = ... dy.name | NoSQLCodeInjection.js:19:36:19:43 | req.body | NoSQLCodeInjection.js:19:24:19:48 | "name = ... dy.name | This code execution depends on a $@. | NoSQLCodeInjection.js:19:36:19:43 | req.body | user-provided value |
@@ -340,20 +364,20 @@ edges
| react-native.js:8:32:8:38 | tainted | react-native.js:7:17:7:33 | req.param("code") | react-native.js:8:32:8:38 | tainted | This code execution depends on a $@. | react-native.js:7:17:7:33 | req.param("code") | user-provided value |
| react-native.js:10:23:10:29 | tainted | react-native.js:7:17:7:33 | req.param("code") | react-native.js:10:23:10:29 | tainted | This code execution depends on a $@. | react-native.js:7:17:7:33 | req.param("code") | user-provided value |
| react.js:10:56:10:77 | documen ... on.hash | react.js:10:56:10:77 | documen ... on.hash | react.js:10:56:10:77 | documen ... on.hash | This code execution depends on a $@. | react.js:10:56:10:77 | documen ... on.hash | user-provided value |
-| template-sinks.js:19:17:19:23 | tainted | template-sinks.js:17:19:17:31 | req.query.foo | template-sinks.js:19:17:19:23 | tainted | Template, which may contain code, depends on a $@. | template-sinks.js:17:19:17:31 | req.query.foo | user-provided value |
-| template-sinks.js:20:16:20:22 | tainted | template-sinks.js:17:19:17:31 | req.query.foo | template-sinks.js:20:16:20:22 | tainted | Template, which may contain code, depends on a $@. | template-sinks.js:17:19:17:31 | req.query.foo | user-provided value |
-| template-sinks.js:21:18:21:24 | tainted | template-sinks.js:17:19:17:31 | req.query.foo | template-sinks.js:21:18:21:24 | tainted | Template, which may contain code, depends on a $@. | template-sinks.js:17:19:17:31 | req.query.foo | user-provided value |
-| template-sinks.js:22:17:22:23 | tainted | template-sinks.js:17:19:17:31 | req.query.foo | template-sinks.js:22:17:22:23 | tainted | Template, which may contain code, depends on a $@. | template-sinks.js:17:19:17:31 | req.query.foo | user-provided value |
-| template-sinks.js:23:18:23:24 | tainted | template-sinks.js:17:19:17:31 | req.query.foo | template-sinks.js:23:18:23:24 | tainted | Template, which may contain code, depends on a $@. | template-sinks.js:17:19:17:31 | req.query.foo | user-provided value |
-| template-sinks.js:24:16:24:22 | tainted | template-sinks.js:17:19:17:31 | req.query.foo | template-sinks.js:24:16:24:22 | tainted | Template, which may contain code, depends on a $@. | template-sinks.js:17:19:17:31 | req.query.foo | user-provided value |
-| template-sinks.js:25:27:25:33 | tainted | template-sinks.js:17:19:17:31 | req.query.foo | template-sinks.js:25:27:25:33 | tainted | Template, which may contain code, depends on a $@. | template-sinks.js:17:19:17:31 | req.query.foo | user-provided value |
-| template-sinks.js:26:21:26:27 | tainted | template-sinks.js:17:19:17:31 | req.query.foo | template-sinks.js:26:21:26:27 | tainted | Template, which may contain code, depends on a $@. | template-sinks.js:17:19:17:31 | req.query.foo | user-provided value |
-| template-sinks.js:27:17:27:23 | tainted | template-sinks.js:17:19:17:31 | req.query.foo | template-sinks.js:27:17:27:23 | tainted | Template, which may contain code, depends on a $@. | template-sinks.js:17:19:17:31 | req.query.foo | user-provided value |
-| template-sinks.js:28:24:28:30 | tainted | template-sinks.js:17:19:17:31 | req.query.foo | template-sinks.js:28:24:28:30 | tainted | Template, which may contain code, depends on a $@. | template-sinks.js:17:19:17:31 | req.query.foo | user-provided value |
-| template-sinks.js:29:21:29:27 | tainted | template-sinks.js:17:19:17:31 | req.query.foo | template-sinks.js:29:21:29:27 | tainted | Template, which may contain code, depends on a $@. | template-sinks.js:17:19:17:31 | req.query.foo | user-provided value |
-| template-sinks.js:30:19:30:25 | tainted | template-sinks.js:17:19:17:31 | req.query.foo | template-sinks.js:30:19:30:25 | tainted | Template, which may contain code, depends on a $@. | template-sinks.js:17:19:17:31 | req.query.foo | user-provided value |
-| template-sinks.js:31:16:31:22 | tainted | template-sinks.js:17:19:17:31 | req.query.foo | template-sinks.js:31:16:31:22 | tainted | Template, which may contain code, depends on a $@. | template-sinks.js:17:19:17:31 | req.query.foo | user-provided value |
-| template-sinks.js:32:17:32:23 | tainted | template-sinks.js:17:19:17:31 | req.query.foo | template-sinks.js:32:17:32:23 | tainted | Template, which may contain code, depends on a $@. | template-sinks.js:17:19:17:31 | req.query.foo | user-provided value |
+| template-sinks.js:20:17:20:23 | tainted | template-sinks.js:18:19:18:31 | req.query.foo | template-sinks.js:20:17:20:23 | tainted | Template, which may contain code, depends on a $@. | template-sinks.js:18:19:18:31 | req.query.foo | user-provided value |
+| template-sinks.js:21:16:21:22 | tainted | template-sinks.js:18:19:18:31 | req.query.foo | template-sinks.js:21:16:21:22 | tainted | Template, which may contain code, depends on a $@. | template-sinks.js:18:19:18:31 | req.query.foo | user-provided value |
+| template-sinks.js:22:18:22:24 | tainted | template-sinks.js:18:19:18:31 | req.query.foo | template-sinks.js:22:18:22:24 | tainted | Template, which may contain code, depends on a $@. | template-sinks.js:18:19:18:31 | req.query.foo | user-provided value |
+| template-sinks.js:23:17:23:23 | tainted | template-sinks.js:18:19:18:31 | req.query.foo | template-sinks.js:23:17:23:23 | tainted | Template, which may contain code, depends on a $@. | template-sinks.js:18:19:18:31 | req.query.foo | user-provided value |
+| template-sinks.js:24:18:24:24 | tainted | template-sinks.js:18:19:18:31 | req.query.foo | template-sinks.js:24:18:24:24 | tainted | Template, which may contain code, depends on a $@. | template-sinks.js:18:19:18:31 | req.query.foo | user-provided value |
+| template-sinks.js:25:16:25:22 | tainted | template-sinks.js:18:19:18:31 | req.query.foo | template-sinks.js:25:16:25:22 | tainted | Template, which may contain code, depends on a $@. | template-sinks.js:18:19:18:31 | req.query.foo | user-provided value |
+| template-sinks.js:26:27:26:33 | tainted | template-sinks.js:18:19:18:31 | req.query.foo | template-sinks.js:26:27:26:33 | tainted | Template, which may contain code, depends on a $@. | template-sinks.js:18:19:18:31 | req.query.foo | user-provided value |
+| template-sinks.js:27:21:27:27 | tainted | template-sinks.js:18:19:18:31 | req.query.foo | template-sinks.js:27:21:27:27 | tainted | Template, which may contain code, depends on a $@. | template-sinks.js:18:19:18:31 | req.query.foo | user-provided value |
+| template-sinks.js:28:17:28:23 | tainted | template-sinks.js:18:19:18:31 | req.query.foo | template-sinks.js:28:17:28:23 | tainted | Template, which may contain code, depends on a $@. | template-sinks.js:18:19:18:31 | req.query.foo | user-provided value |
+| template-sinks.js:29:24:29:30 | tainted | template-sinks.js:18:19:18:31 | req.query.foo | template-sinks.js:29:24:29:30 | tainted | Template, which may contain code, depends on a $@. | template-sinks.js:18:19:18:31 | req.query.foo | user-provided value |
+| template-sinks.js:30:21:30:27 | tainted | template-sinks.js:18:19:18:31 | req.query.foo | template-sinks.js:30:21:30:27 | tainted | Template, which may contain code, depends on a $@. | template-sinks.js:18:19:18:31 | req.query.foo | user-provided value |
+| template-sinks.js:31:19:31:25 | tainted | template-sinks.js:18:19:18:31 | req.query.foo | template-sinks.js:31:19:31:25 | tainted | Template, which may contain code, depends on a $@. | template-sinks.js:18:19:18:31 | req.query.foo | user-provided value |
+| template-sinks.js:32:16:32:22 | tainted | template-sinks.js:18:19:18:31 | req.query.foo | template-sinks.js:32:16:32:22 | tainted | Template, which may contain code, depends on a $@. | template-sinks.js:18:19:18:31 | req.query.foo | user-provided value |
+| template-sinks.js:33:17:33:23 | tainted | template-sinks.js:18:19:18:31 | req.query.foo | template-sinks.js:33:17:33:23 | tainted | Template, which may contain code, depends on a $@. | template-sinks.js:18:19:18:31 | req.query.foo | user-provided value |
| tst.js:2:6:2:83 | documen ... t=")+8) | tst.js:2:6:2:27 | documen ... on.href | tst.js:2:6:2:83 | documen ... t=")+8) | This code execution depends on a $@. | tst.js:2:6:2:27 | documen ... on.href | user-provided value |
| tst.js:5:12:5:33 | documen ... on.hash | tst.js:5:12:5:33 | documen ... on.hash | tst.js:5:12:5:33 | documen ... on.hash | This code execution depends on a $@. | tst.js:5:12:5:33 | documen ... on.hash | user-provided value |
| tst.js:14:10:14:74 | documen ... , "$1") | tst.js:14:10:14:33 | documen ... .search | tst.js:14:10:14:74 | documen ... , "$1") | This code execution depends on a $@. | tst.js:14:10:14:33 | documen ... .search | user-provided value |
@@ -365,3 +389,9 @@ edges
| tst.js:33:14:33:19 | source | tst.js:29:18:29:41 | documen ... .search | tst.js:33:14:33:19 | source | This code execution depends on a $@. | tst.js:29:18:29:41 | documen ... .search | user-provided value |
| tst.js:35:28:35:33 | source | tst.js:29:18:29:41 | documen ... .search | tst.js:35:28:35:33 | source | This code execution depends on a $@. | tst.js:29:18:29:41 | documen ... .search | user-provided value |
| tst.js:37:33:37:38 | source | tst.js:29:18:29:41 | documen ... .search | tst.js:37:33:37:38 | source | This code execution depends on a $@. | tst.js:29:18:29:41 | documen ... .search | user-provided value |
+| webix/webix.html:3:16:3:37 | documen ... on.hash | webix/webix.html:3:16:3:37 | documen ... on.hash | webix/webix.html:3:16:3:37 | documen ... on.hash | This code execution depends on a $@. | webix/webix.html:3:16:3:37 | documen ... on.hash | user-provided value |
+| webix/webix.html:4:26:4:47 | documen ... on.hash | webix/webix.html:4:26:4:47 | documen ... on.hash | webix/webix.html:4:26:4:47 | documen ... on.hash | Template, which may contain code, depends on a $@. | webix/webix.html:4:26:4:47 | documen ... on.hash | user-provided value |
+| webix/webix.html:5:47:5:68 | documen ... on.hash | webix/webix.html:5:47:5:68 | documen ... on.hash | webix/webix.html:5:47:5:68 | documen ... on.hash | Template, which may contain code, depends on a $@. | webix/webix.html:5:47:5:68 | documen ... on.hash | user-provided value |
+| webix/webix.js:3:12:3:33 | documen ... on.hash | webix/webix.js:3:12:3:33 | documen ... on.hash | webix/webix.js:3:12:3:33 | documen ... on.hash | This code execution depends on a $@. | webix/webix.js:3:12:3:33 | documen ... on.hash | user-provided value |
+| webix/webix.js:4:22:4:43 | documen ... on.hash | webix/webix.js:4:22:4:43 | documen ... on.hash | webix/webix.js:4:22:4:43 | documen ... on.hash | Template, which may contain code, depends on a $@. | webix/webix.js:4:22:4:43 | documen ... on.hash | user-provided value |
+| webix/webix.js:5:43:5:64 | documen ... on.hash | webix/webix.js:5:43:5:64 | documen ... on.hash | webix/webix.js:5:43:5:64 | documen ... on.hash | Template, which may contain code, depends on a $@. | webix/webix.js:5:43:5:64 | documen ... on.hash | user-provided value |
diff --git a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/HeuristicSourceCodeInjection.expected b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/HeuristicSourceCodeInjection.expected
index be221820c070..7e4bd3059551 100644
--- a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/HeuristicSourceCodeInjection.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/HeuristicSourceCodeInjection.expected
@@ -116,37 +116,37 @@ nodes
| react.js:10:56:10:77 | documen ... on.hash |
| react.js:10:56:10:77 | documen ... on.hash |
| react.js:10:56:10:77 | documen ... on.hash |
-| template-sinks.js:17:9:17:31 | tainted |
-| template-sinks.js:17:19:17:31 | req.query.foo |
-| template-sinks.js:17:19:17:31 | req.query.foo |
-| template-sinks.js:19:17:19:23 | tainted |
-| template-sinks.js:19:17:19:23 | tainted |
-| template-sinks.js:20:16:20:22 | tainted |
-| template-sinks.js:20:16:20:22 | tainted |
-| template-sinks.js:21:18:21:24 | tainted |
-| template-sinks.js:21:18:21:24 | tainted |
-| template-sinks.js:22:17:22:23 | tainted |
-| template-sinks.js:22:17:22:23 | tainted |
-| template-sinks.js:23:18:23:24 | tainted |
-| template-sinks.js:23:18:23:24 | tainted |
-| template-sinks.js:24:16:24:22 | tainted |
-| template-sinks.js:24:16:24:22 | tainted |
-| template-sinks.js:25:27:25:33 | tainted |
-| template-sinks.js:25:27:25:33 | tainted |
-| template-sinks.js:26:21:26:27 | tainted |
-| template-sinks.js:26:21:26:27 | tainted |
-| template-sinks.js:27:17:27:23 | tainted |
-| template-sinks.js:27:17:27:23 | tainted |
-| template-sinks.js:28:24:28:30 | tainted |
-| template-sinks.js:28:24:28:30 | tainted |
-| template-sinks.js:29:21:29:27 | tainted |
-| template-sinks.js:29:21:29:27 | tainted |
-| template-sinks.js:30:19:30:25 | tainted |
-| template-sinks.js:30:19:30:25 | tainted |
-| template-sinks.js:31:16:31:22 | tainted |
-| template-sinks.js:31:16:31:22 | tainted |
-| template-sinks.js:32:17:32:23 | tainted |
-| template-sinks.js:32:17:32:23 | tainted |
+| template-sinks.js:18:9:18:31 | tainted |
+| template-sinks.js:18:19:18:31 | req.query.foo |
+| template-sinks.js:18:19:18:31 | req.query.foo |
+| template-sinks.js:20:17:20:23 | tainted |
+| template-sinks.js:20:17:20:23 | tainted |
+| template-sinks.js:21:16:21:22 | tainted |
+| template-sinks.js:21:16:21:22 | tainted |
+| template-sinks.js:22:18:22:24 | tainted |
+| template-sinks.js:22:18:22:24 | tainted |
+| template-sinks.js:23:17:23:23 | tainted |
+| template-sinks.js:23:17:23:23 | tainted |
+| template-sinks.js:24:18:24:24 | tainted |
+| template-sinks.js:24:18:24:24 | tainted |
+| template-sinks.js:25:16:25:22 | tainted |
+| template-sinks.js:25:16:25:22 | tainted |
+| template-sinks.js:26:27:26:33 | tainted |
+| template-sinks.js:26:27:26:33 | tainted |
+| template-sinks.js:27:21:27:27 | tainted |
+| template-sinks.js:27:21:27:27 | tainted |
+| template-sinks.js:28:17:28:23 | tainted |
+| template-sinks.js:28:17:28:23 | tainted |
+| template-sinks.js:29:24:29:30 | tainted |
+| template-sinks.js:29:24:29:30 | tainted |
+| template-sinks.js:30:21:30:27 | tainted |
+| template-sinks.js:30:21:30:27 | tainted |
+| template-sinks.js:31:19:31:25 | tainted |
+| template-sinks.js:31:19:31:25 | tainted |
+| template-sinks.js:32:16:32:22 | tainted |
+| template-sinks.js:32:16:32:22 | tainted |
+| template-sinks.js:33:17:33:23 | tainted |
+| template-sinks.js:33:17:33:23 | tainted |
| tst.js:2:6:2:27 | documen ... on.href |
| tst.js:2:6:2:27 | documen ... on.href |
| tst.js:2:6:2:83 | documen ... t=")+8) |
@@ -185,6 +185,24 @@ nodes
| tst.js:35:28:35:33 | source |
| tst.js:37:33:37:38 | source |
| tst.js:37:33:37:38 | source |
+| webix/webix.html:3:16:3:37 | documen ... on.hash |
+| webix/webix.html:3:16:3:37 | documen ... on.hash |
+| webix/webix.html:3:16:3:37 | documen ... on.hash |
+| webix/webix.html:4:26:4:47 | documen ... on.hash |
+| webix/webix.html:4:26:4:47 | documen ... on.hash |
+| webix/webix.html:4:26:4:47 | documen ... on.hash |
+| webix/webix.html:5:47:5:68 | documen ... on.hash |
+| webix/webix.html:5:47:5:68 | documen ... on.hash |
+| webix/webix.html:5:47:5:68 | documen ... on.hash |
+| webix/webix.js:3:12:3:33 | documen ... on.hash |
+| webix/webix.js:3:12:3:33 | documen ... on.hash |
+| webix/webix.js:3:12:3:33 | documen ... on.hash |
+| webix/webix.js:4:22:4:43 | documen ... on.hash |
+| webix/webix.js:4:22:4:43 | documen ... on.hash |
+| webix/webix.js:4:22:4:43 | documen ... on.hash |
+| webix/webix.js:5:43:5:64 | documen ... on.hash |
+| webix/webix.js:5:43:5:64 | documen ... on.hash |
+| webix/webix.js:5:43:5:64 | documen ... on.hash |
edges
| NoSQLCodeInjection.js:18:24:18:31 | req.body | NoSQLCodeInjection.js:18:24:18:37 | req.body.query |
| NoSQLCodeInjection.js:18:24:18:31 | req.body | NoSQLCodeInjection.js:18:24:18:37 | req.body.query |
@@ -254,36 +272,36 @@ edges
| react-native.js:7:17:7:33 | req.param("code") | react-native.js:7:7:7:33 | tainted |
| react-native.js:7:17:7:33 | req.param("code") | react-native.js:7:7:7:33 | tainted |
| react.js:10:56:10:77 | documen ... on.hash | react.js:10:56:10:77 | documen ... on.hash |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:19:17:19:23 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:19:17:19:23 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:20:16:20:22 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:20:16:20:22 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:21:18:21:24 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:21:18:21:24 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:22:17:22:23 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:22:17:22:23 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:23:18:23:24 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:23:18:23:24 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:24:16:24:22 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:24:16:24:22 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:25:27:25:33 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:25:27:25:33 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:26:21:26:27 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:26:21:26:27 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:27:17:27:23 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:27:17:27:23 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:28:24:28:30 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:28:24:28:30 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:29:21:29:27 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:29:21:29:27 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:30:19:30:25 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:30:19:30:25 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:31:16:31:22 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:31:16:31:22 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:32:17:32:23 | tainted |
-| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:32:17:32:23 | tainted |
-| template-sinks.js:17:19:17:31 | req.query.foo | template-sinks.js:17:9:17:31 | tainted |
-| template-sinks.js:17:19:17:31 | req.query.foo | template-sinks.js:17:9:17:31 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:20:17:20:23 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:20:17:20:23 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:21:16:21:22 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:21:16:21:22 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:22:18:22:24 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:22:18:22:24 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:23:17:23:23 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:23:17:23:23 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:24:18:24:24 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:24:18:24:24 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:25:16:25:22 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:25:16:25:22 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:26:27:26:33 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:26:27:26:33 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:27:21:27:27 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:27:21:27:27 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:28:17:28:23 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:28:17:28:23 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:29:24:29:30 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:29:24:29:30 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:30:21:30:27 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:30:21:30:27 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:31:19:31:25 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:31:19:31:25 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:32:16:32:22 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:32:16:32:22 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:33:17:33:23 | tainted |
+| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:33:17:33:23 | tainted |
+| template-sinks.js:18:19:18:31 | req.query.foo | template-sinks.js:18:9:18:31 | tainted |
+| template-sinks.js:18:19:18:31 | req.query.foo | template-sinks.js:18:9:18:31 | tainted |
| tst.js:2:6:2:27 | documen ... on.href | tst.js:2:6:2:83 | documen ... t=")+8) |
| tst.js:2:6:2:27 | documen ... on.href | tst.js:2:6:2:83 | documen ... t=")+8) |
| tst.js:2:6:2:27 | documen ... on.href | tst.js:2:6:2:83 | documen ... t=")+8) |
@@ -314,5 +332,11 @@ edges
| tst.js:29:18:29:41 | documen ... .search | tst.js:29:18:29:82 | documen ... , "$1") |
| tst.js:29:18:29:41 | documen ... .search | tst.js:29:18:29:82 | documen ... , "$1") |
| tst.js:29:18:29:82 | documen ... , "$1") | tst.js:29:9:29:82 | source |
+| webix/webix.html:3:16:3:37 | documen ... on.hash | webix/webix.html:3:16:3:37 | documen ... on.hash |
+| webix/webix.html:4:26:4:47 | documen ... on.hash | webix/webix.html:4:26:4:47 | documen ... on.hash |
+| webix/webix.html:5:47:5:68 | documen ... on.hash | webix/webix.html:5:47:5:68 | documen ... on.hash |
+| webix/webix.js:3:12:3:33 | documen ... on.hash | webix/webix.js:3:12:3:33 | documen ... on.hash |
+| webix/webix.js:4:22:4:43 | documen ... on.hash | webix/webix.js:4:22:4:43 | documen ... on.hash |
+| webix/webix.js:5:43:5:64 | documen ... on.hash | webix/webix.js:5:43:5:64 | documen ... on.hash |
#select
| eslint-escope-build.js:21:16:21:16 | c | eslint-escope-build.js:20:22:20:22 | c | eslint-escope-build.js:21:16:21:16 | c | $@ flows to here and is interpreted as code. | eslint-escope-build.js:20:22:20:22 | c | User-provided value |
diff --git a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/template-sinks.js b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/template-sinks.js
index f2cc7a400f63..51554663e4ee 100644
--- a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/template-sinks.js
+++ b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/template-sinks.js
@@ -10,10 +10,11 @@ import * as mustache from 'mustache';
const Hogan = require("hogan.js");
import * as Eta from 'eta';
import * as Sqrl from 'squirrelly'
+import * as webix from "webix";
var app = express();
-app.get('/some/path', function(req, res) {
+app.get('/some/path', function (req, res) {
let tainted = req.query.foo;
pug.compile(tainted); // NOT OK
diff --git a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/webix/webix.html b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/webix/webix.html
new file mode 100644
index 000000000000..3f62fd326211
--- /dev/null
+++ b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/webix/webix.html
@@ -0,0 +1,6 @@
+
+
\ No newline at end of file
diff --git a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/webix/webix.js b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/webix/webix.js
new file mode 100644
index 000000000000..00fb98af9675
--- /dev/null
+++ b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/webix/webix.js
@@ -0,0 +1,5 @@
+import * as webix from 'webix';
+
+webix.exec(document.location.hash); // NOT OK
+webix.ui({ template: document.location.hash }); // NOT OK
+webix.ui({ template: function () { return document.location.hash } }); // NOT OK
\ No newline at end of file
diff --git a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/PrototypePollutingMergeCall.expected b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/PrototypePollutingMergeCall.expected
index f7b8f8df1d37..a697bd247604 100644
--- a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/PrototypePollutingMergeCall.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/PrototypePollutingMergeCall.expected
@@ -17,6 +17,26 @@ nodes
| src-vulnerable-lodash/tst.js:17:17:19:5 | {\\n ... K\\n } |
| src-vulnerable-lodash/tst.js:17:17:19:5 | {\\n ... K\\n } |
| src-vulnerable-lodash/tst.js:18:16:18:25 | opts.thing |
+| webix/webix.html:3:34:3:38 | event |
+| webix/webix.html:3:34:3:38 | event |
+| webix/webix.html:4:26:4:47 | JSON.pa ... t.data) |
+| webix/webix.html:4:26:4:47 | JSON.pa ... t.data) |
+| webix/webix.html:4:37:4:41 | event |
+| webix/webix.html:4:37:4:46 | event.data |
+| webix/webix.html:5:24:5:45 | JSON.pa ... t.data) |
+| webix/webix.html:5:24:5:45 | JSON.pa ... t.data) |
+| webix/webix.html:5:35:5:39 | event |
+| webix/webix.html:5:35:5:44 | event.data |
+| webix/webix.js:3:30:3:34 | event |
+| webix/webix.js:3:30:3:34 | event |
+| webix/webix.js:4:22:4:43 | JSON.pa ... t.data) |
+| webix/webix.js:4:22:4:43 | JSON.pa ... t.data) |
+| webix/webix.js:4:33:4:37 | event |
+| webix/webix.js:4:33:4:42 | event.data |
+| webix/webix.js:5:20:5:41 | JSON.pa ... t.data) |
+| webix/webix.js:5:20:5:41 | JSON.pa ... t.data) |
+| webix/webix.js:5:31:5:35 | event |
+| webix/webix.js:5:31:5:40 | event.data |
edges
| angularmerge.js:1:30:1:34 | event | angularmerge.js:2:32:2:36 | event |
| angularmerge.js:1:30:1:34 | event | angularmerge.js:2:32:2:36 | event |
@@ -32,8 +52,32 @@ edges
| src-vulnerable-lodash/tst.js:15:14:15:28 | req.query.value | src-vulnerable-lodash/tst.js:18:16:18:25 | opts.thing |
| src-vulnerable-lodash/tst.js:18:16:18:25 | opts.thing | src-vulnerable-lodash/tst.js:17:17:19:5 | {\\n ... K\\n } |
| src-vulnerable-lodash/tst.js:18:16:18:25 | opts.thing | src-vulnerable-lodash/tst.js:17:17:19:5 | {\\n ... K\\n } |
+| webix/webix.html:3:34:3:38 | event | webix/webix.html:4:37:4:41 | event |
+| webix/webix.html:3:34:3:38 | event | webix/webix.html:4:37:4:41 | event |
+| webix/webix.html:3:34:3:38 | event | webix/webix.html:5:35:5:39 | event |
+| webix/webix.html:3:34:3:38 | event | webix/webix.html:5:35:5:39 | event |
+| webix/webix.html:4:37:4:41 | event | webix/webix.html:4:37:4:46 | event.data |
+| webix/webix.html:4:37:4:46 | event.data | webix/webix.html:4:26:4:47 | JSON.pa ... t.data) |
+| webix/webix.html:4:37:4:46 | event.data | webix/webix.html:4:26:4:47 | JSON.pa ... t.data) |
+| webix/webix.html:5:35:5:39 | event | webix/webix.html:5:35:5:44 | event.data |
+| webix/webix.html:5:35:5:44 | event.data | webix/webix.html:5:24:5:45 | JSON.pa ... t.data) |
+| webix/webix.html:5:35:5:44 | event.data | webix/webix.html:5:24:5:45 | JSON.pa ... t.data) |
+| webix/webix.js:3:30:3:34 | event | webix/webix.js:4:33:4:37 | event |
+| webix/webix.js:3:30:3:34 | event | webix/webix.js:4:33:4:37 | event |
+| webix/webix.js:3:30:3:34 | event | webix/webix.js:5:31:5:35 | event |
+| webix/webix.js:3:30:3:34 | event | webix/webix.js:5:31:5:35 | event |
+| webix/webix.js:4:33:4:37 | event | webix/webix.js:4:33:4:42 | event.data |
+| webix/webix.js:4:33:4:42 | event.data | webix/webix.js:4:22:4:43 | JSON.pa ... t.data) |
+| webix/webix.js:4:33:4:42 | event.data | webix/webix.js:4:22:4:43 | JSON.pa ... t.data) |
+| webix/webix.js:5:31:5:35 | event | webix/webix.js:5:31:5:40 | event.data |
+| webix/webix.js:5:31:5:40 | event.data | webix/webix.js:5:20:5:41 | JSON.pa ... t.data) |
+| webix/webix.js:5:31:5:40 | event.data | webix/webix.js:5:20:5:41 | JSON.pa ... t.data) |
#select
| angularmerge.js:2:21:2:42 | JSON.pa ... t.data) | angularmerge.js:1:30:1:34 | event | angularmerge.js:2:21:2:42 | JSON.pa ... t.data) | Prototype pollution caused by merging a $@ using a vulnerable version of $@. | angularmerge.js:1:30:1:34 | event | user-controlled value | angularmerge.js:2:3:2:43 | angular ... .data)) | angular |
| src-vulnerable-lodash/tst.js:7:17:7:29 | req.query.foo | src-vulnerable-lodash/tst.js:7:17:7:29 | req.query.foo | src-vulnerable-lodash/tst.js:7:17:7:29 | req.query.foo | Prototype pollution caused by merging a $@ using a vulnerable version of $@. | src-vulnerable-lodash/tst.js:7:17:7:29 | req.query.foo | user-controlled value | src-vulnerable-lodash/package.json:3:19:3:26 | "4.17.4" | lodash |
| src-vulnerable-lodash/tst.js:10:17:12:5 | {\\n ... K\\n } | src-vulnerable-lodash/tst.js:11:16:11:30 | req.query.value | src-vulnerable-lodash/tst.js:10:17:12:5 | {\\n ... K\\n } | Prototype pollution caused by merging a $@ using a vulnerable version of $@. | src-vulnerable-lodash/tst.js:11:16:11:30 | req.query.value | user-controlled value | src-vulnerable-lodash/package.json:3:19:3:26 | "4.17.4" | lodash |
| src-vulnerable-lodash/tst.js:17:17:19:5 | {\\n ... K\\n } | src-vulnerable-lodash/tst.js:15:14:15:28 | req.query.value | src-vulnerable-lodash/tst.js:17:17:19:5 | {\\n ... K\\n } | Prototype pollution caused by merging a $@ using a vulnerable version of $@. | src-vulnerable-lodash/tst.js:15:14:15:28 | req.query.value | user-controlled value | src-vulnerable-lodash/package.json:3:19:3:26 | "4.17.4" | lodash |
+| webix/webix.html:4:26:4:47 | JSON.pa ... t.data) | webix/webix.html:3:34:3:38 | event | webix/webix.html:4:26:4:47 | JSON.pa ... t.data) | Prototype pollution caused by merging a $@ using a vulnerable version of $@. | webix/webix.html:3:34:3:38 | event | user-controlled value | webix/webix.html:4:9:4:48 | webix.e ... .data)) | webix |
+| webix/webix.html:5:24:5:45 | JSON.pa ... t.data) | webix/webix.html:3:34:3:38 | event | webix/webix.html:5:24:5:45 | JSON.pa ... t.data) | Prototype pollution caused by merging a $@ using a vulnerable version of $@. | webix/webix.html:3:34:3:38 | event | user-controlled value | webix/webix.html:5:9:5:46 | webix.c ... .data)) | webix |
+| webix/webix.js:4:22:4:43 | JSON.pa ... t.data) | webix/webix.js:3:30:3:34 | event | webix/webix.js:4:22:4:43 | JSON.pa ... t.data) | Prototype pollution caused by merging a $@ using a vulnerable version of $@. | webix/webix.js:3:30:3:34 | event | user-controlled value | webix/webix.js:4:5:4:44 | webix.e ... .data)) | webix |
+| webix/webix.js:5:20:5:41 | JSON.pa ... t.data) | webix/webix.js:3:30:3:34 | event | webix/webix.js:5:20:5:41 | JSON.pa ... t.data) | Prototype pollution caused by merging a $@ using a vulnerable version of $@. | webix/webix.js:3:30:3:34 | event | user-controlled value | webix/webix.js:5:5:5:42 | webix.c ... .data)) | webix |
diff --git a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/webix/webix.html b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/webix/webix.html
new file mode 100644
index 000000000000..02d6d086d547
--- /dev/null
+++ b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/webix/webix.html
@@ -0,0 +1,7 @@
+
+
\ No newline at end of file
diff --git a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/webix/webix.js b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/webix/webix.js
new file mode 100644
index 000000000000..acbfa2acbb42
--- /dev/null
+++ b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/webix/webix.js
@@ -0,0 +1,6 @@
+import * as webix from "webix";
+
+addEventListener("message", (event) => {
+ webix.extend({}, JSON.parse(event.data)); // NOT OK
+ webix.copy({}, JSON.parse(event.data)); // NOT OK
+});