From 6947e99c1545f77b81dd99e539d601b0c72074b7 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Thu, 22 Jun 2023 01:07:33 +0200 Subject: [PATCH 01/11] Add models for `webix` Co-authored-by: Kevin Stubbings --- javascript/ql/lib/javascript.qll | 1 + .../ql/lib/semmle/javascript/Extend.qll | 3 +- .../dataflow/CodeInjectionCustomizations.qll | 24 +++ .../PrototypePollutionCustomizations.qll | 4 + .../CodeInjection/CodeInjection.expected | 165 ++++++++++-------- .../CWE-094/CodeInjection/template-sinks.js | 5 +- .../Security/CWE-094/CodeInjection/webix.js | 3 + .../PrototypePollutingMergeCall.expected | 12 ++ .../PrototypePollutingMergeCall/webix.js | 5 + 9 files changed, 145 insertions(+), 77 deletions(-) create mode 100644 javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/webix.js create mode 100644 javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/webix.js 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..1b3204914ef8 100644 --- a/javascript/ql/lib/semmle/javascript/Extend.qll +++ b/javascript/ql/lib/semmle/javascript/Extend.qll @@ -96,7 +96,8 @@ 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").getAPropertyRead("extend") ) } diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll index 5d658b23b592..5d1a9bc28969 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 = DataFlow::moduleImport("webix").getAMemberCall("exec").getArgument(0) } + } + /** A sink for code injection via template injection. */ abstract private class TemplateSink extends Sink { deprecated override string getMessageSuffix() { @@ -419,6 +426,23 @@ module CodeInjection { } } + /** + * A value interpreted as a template by the `webix` library. + */ + class WebixTemplateSink extends TemplateSink { + WebixTemplateSink() { + this = DataFlow::moduleImport("webix").getAMemberCall("ui").getOptionArgument(0, "template") + or + this.asExpr() = + DataFlow::moduleImport("webix") + .getAMemberCall("ui") + .getOptionArgument(0, "template") + .asExpr() + .(Function) + .getAReturnedExpr() + } + } + /** * 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..cc82792abf45 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 = DataFlow::moduleImport("webix").getAMemberCall("extend") 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..cc3175a3645c 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,41 @@ 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 | +| template-sinks.js:34:26:34:32 | tainted | +| template-sinks.js:34:26:34:32 | tainted | +| template-sinks.js:35:47:35:53 | tainted | +| template-sinks.js:35:47:35:53 | 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 +185,9 @@ nodes | tst.js:35:28:35:33 | source | | tst.js:37:33:37:38 | source | | tst.js:37:33:37:38 | source | +| webix.js:3:12:3:33 | documen ... on.hash | +| webix.js:3:12:3:33 | documen ... on.hash | +| webix.js:3:12:3:33 | 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 +253,40 @@ 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:9:18:31 | tainted | template-sinks.js:34:26:34:32 | tainted | +| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:34:26:34:32 | tainted | +| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:35:47:35:53 | tainted | +| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:35:47:35:53 | 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 +317,7 @@ 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.js:3:12:3:33 | documen ... on.hash | webix.js:3:12:3:33 | 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 +352,22 @@ 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 | +| template-sinks.js:34:26:34:32 | tainted | template-sinks.js:18:19:18:31 | req.query.foo | template-sinks.js:34:26:34:32 | 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:35:47:35:53 | tainted | template-sinks.js:18:19:18:31 | req.query.foo | template-sinks.js:35:47:35:53 | 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 +379,4 @@ 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.js:3:12:3:33 | documen ... on.hash | webix.js:3:12:3:33 | documen ... on.hash | webix.js:3:12:3:33 | documen ... on.hash | This code execution depends on a $@. | webix.js:3:12:3:33 | documen ... on.hash | 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..7c8e310cd1f4 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 @@ -30,4 +31,6 @@ app.get('/some/path', function(req, res) { Hogan.compile(tainted); // NOT OK Eta.render(tainted); // NOT OK Sqrl.render(tainted); // NOT OK + webix.ui({ template: tainted }); // NOT OK + webix.ui({ template: function () { return tainted } }) // NOT OK }); diff --git a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/webix.js b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/webix.js new file mode 100644 index 000000000000..289bffe22b47 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/webix.js @@ -0,0 +1,3 @@ +import * as webix from 'webix'; + +webix.exec(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..4664d64a7425 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,12 @@ 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.js:3:30:3:34 | event | +| webix.js:3:30:3:34 | event | +| webix.js:4:22:4:43 | JSON.pa ... t.data) | +| webix.js:4:22:4:43 | JSON.pa ... t.data) | +| webix.js:4:33:4:37 | event | +| webix.js:4:33:4:42 | 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 +38,14 @@ 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.js:3:30:3:34 | event | webix.js:4:33:4:37 | event | +| webix.js:3:30:3:34 | event | webix.js:4:33:4:37 | event | +| webix.js:4:33:4:37 | event | webix.js:4:33:4:42 | event.data | +| webix.js:4:33:4:42 | event.data | webix.js:4:22:4:43 | JSON.pa ... t.data) | +| webix.js:4:33:4:42 | event.data | webix.js:4:22:4:43 | 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.js:4:22:4:43 | JSON.pa ... t.data) | webix.js:3:30:3:34 | event | webix.js:4:22:4:43 | JSON.pa ... t.data) | Prototype pollution caused by merging a $@ using a vulnerable version of $@. | webix.js:3:30:3:34 | event | user-controlled value | webix.js:4:5:4:44 | webix.e ... .data)) | webix | diff --git a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/webix.js b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/webix.js new file mode 100644 index 000000000000..85983bb0af7f --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/webix.js @@ -0,0 +1,5 @@ +import * as webix from "webix"; + +addEventListener("message", (event) => { + webix.extend({}, JSON.parse(event.data)); // NOT OK +}); From 868129c7e7f1981360724c56cc33bd6af411f324 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Thu, 22 Jun 2023 01:14:06 +0200 Subject: [PATCH 02/11] Add change note --- javascript/ql/lib/change-notes/2023-06-22-webix.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 javascript/ql/lib/change-notes/2023-06-22-webix.md 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 From 7e7e2aaac70adf8b33389d7aeb1c46d2801e0075 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Thu, 22 Jun 2023 01:15:08 +0200 Subject: [PATCH 03/11] Remove non-existing import --- javascript/ql/lib/javascript.qll | 1 - 1 file changed, 1 deletion(-) diff --git a/javascript/ql/lib/javascript.qll b/javascript/ql/lib/javascript.qll index 07fb759bd655..ed38db6550e2 100644 --- a/javascript/ql/lib/javascript.qll +++ b/javascript/ql/lib/javascript.qll @@ -134,7 +134,6 @@ 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 From 3605269e13bc572651e4223c698c96b91dd23c54 Mon Sep 17 00:00:00 2001 From: Kevin Stubbings Date: Thu, 22 Jun 2023 22:16:28 -0700 Subject: [PATCH 04/11] Add webix copy function --- javascript/ql/lib/semmle/javascript/Extend.qll | 2 +- .../dataflow/PrototypePollutionCustomizations.qll | 2 +- .../PrototypePollutingMergeCall.expected | 10 ++++++++++ .../CWE-915/PrototypePollutingMergeCall/webix.js | 1 + 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/Extend.qll b/javascript/ql/lib/semmle/javascript/Extend.qll index 1b3204914ef8..93f59e70c6ab 100644 --- a/javascript/ql/lib/semmle/javascript/Extend.qll +++ b/javascript/ql/lib/semmle/javascript/Extend.qll @@ -97,7 +97,7 @@ private class ExtendCallDeep extends ExtendCall { callee = LodashUnderscore::member("mergeWith") or callee = LodashUnderscore::member("defaultsDeep") or callee = AngularJS::angular().getAPropertyRead("merge") or - callee = DataFlow::moduleImport("webix").getAPropertyRead("extend") + callee = DataFlow::moduleImport("webix").getAPropertyRead(["extend", "copy"]) ) } diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionCustomizations.qll index cc82792abf45..e3cce57add61 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionCustomizations.qll @@ -173,7 +173,7 @@ module PrototypePollution { id = "angular" or call.isDeep() and - call = DataFlow::moduleImport("webix").getAMemberCall("extend") and + call = DataFlow::moduleImport("webix").getAMemberCall(["extend", "copy"]) and id = "webix" } } 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 4664d64a7425..0699ba81815d 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 @@ -23,6 +23,10 @@ nodes | webix.js:4:22:4:43 | JSON.pa ... t.data) | | webix.js:4:33:4:37 | event | | webix.js:4:33:4:42 | event.data | +| webix.js:5:19:5:40 | JSON.pa ... t.data) | +| webix.js:5:19:5:40 | JSON.pa ... t.data) | +| webix.js:5:30:5:34 | event | +| webix.js:5:30:5:39 | 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 | @@ -40,12 +44,18 @@ edges | src-vulnerable-lodash/tst.js:18:16:18:25 | opts.thing | src-vulnerable-lodash/tst.js:17:17:19:5 | {\\n ... K\\n } | | webix.js:3:30:3:34 | event | webix.js:4:33:4:37 | event | | webix.js:3:30:3:34 | event | webix.js:4:33:4:37 | event | +| webix.js:3:30:3:34 | event | webix.js:5:30:5:34 | event | +| webix.js:3:30:3:34 | event | webix.js:5:30:5:34 | event | | webix.js:4:33:4:37 | event | webix.js:4:33:4:42 | event.data | | webix.js:4:33:4:42 | event.data | webix.js:4:22:4:43 | JSON.pa ... t.data) | | webix.js:4:33:4:42 | event.data | webix.js:4:22:4:43 | JSON.pa ... t.data) | +| webix.js:5:30:5:34 | event | webix.js:5:30:5:39 | event.data | +| webix.js:5:30:5:39 | event.data | webix.js:5:19:5:40 | JSON.pa ... t.data) | +| webix.js:5:30:5:39 | event.data | webix.js:5:19:5:40 | 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.js:4:22:4:43 | JSON.pa ... t.data) | webix.js:3:30:3:34 | event | webix.js:4:22:4:43 | JSON.pa ... t.data) | Prototype pollution caused by merging a $@ using a vulnerable version of $@. | webix.js:3:30:3:34 | event | user-controlled value | webix.js:4:5:4:44 | webix.e ... .data)) | webix | +| webix.js:5:19:5:40 | JSON.pa ... t.data) | webix.js:3:30:3:34 | event | webix.js:5:19:5:40 | JSON.pa ... t.data) | Prototype pollution caused by merging a $@ using a vulnerable version of $@. | webix.js:3:30:3:34 | event | user-controlled value | webix.js:5:5:5:41 | webix.c ... .data)) | webix | diff --git a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/webix.js b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/webix.js index 85983bb0af7f..2116b7d95c8a 100644 --- a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/webix.js +++ b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/webix.js @@ -2,4 +2,5 @@ import * as webix from "webix"; addEventListener("message", (event) => { webix.extend({}, JSON.parse(event.data)); // NOT OK + webix.copy({},JSON.parse(event.data)); // NOT OK }); From 3c980db93aacab64084d77b2aa742482f04d44bf Mon Sep 17 00:00:00 2001 From: Jorge <46056498+jorgectf@users.noreply.github.com> Date: Fri, 23 Jun 2023 18:08:01 +0200 Subject: [PATCH 05/11] Format `webix.js` --- .../Security/CWE-915/PrototypePollutingMergeCall/webix.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/webix.js b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/webix.js index 2116b7d95c8a..acbfa2acbb42 100644 --- a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/webix.js +++ b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/webix.js @@ -2,5 +2,5 @@ import * as webix from "webix"; addEventListener("message", (event) => { webix.extend({}, JSON.parse(event.data)); // NOT OK - webix.copy({},JSON.parse(event.data)); // NOT OK + webix.copy({}, JSON.parse(event.data)); // NOT OK }); From 08b9a5e2b20f32d24fea22f03469a7dc047d5914 Mon Sep 17 00:00:00 2001 From: Jorge <46056498+jorgectf@users.noreply.github.com> Date: Fri, 23 Jun 2023 23:10:06 +0200 Subject: [PATCH 06/11] Add missing `;` --- .../Security/CWE-094/CodeInjection/template-sinks.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 7c8e310cd1f4..5b786cdeee40 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 @@ -32,5 +32,5 @@ app.get('/some/path', function (req, res) { Eta.render(tainted); // NOT OK Sqrl.render(tainted); // NOT OK webix.ui({ template: tainted }); // NOT OK - webix.ui({ template: function () { return tainted } }) // NOT OK + webix.ui({ template: function () { return tainted } }); // NOT OK }); From 5bd044211ebcc76c7040ffbaa27be3ffcf3e9b20 Mon Sep 17 00:00:00 2001 From: Jorge <46056498+jorgectf@users.noreply.github.com> Date: Mon, 26 Jun 2023 13:27:23 +0200 Subject: [PATCH 07/11] Apply suggestions from code review Co-authored-by: Asger F --- .../dataflow/CodeInjectionCustomizations.qll | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll index 5d1a9bc28969..d4e62dba6352 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll @@ -316,7 +316,7 @@ module CodeInjection { * A value interpreted as code by the `webix` library. */ class WebixExec extends Sink { - WebixExec() { this = DataFlow::moduleImport("webix").getAMemberCall("exec").getArgument(0) } + WebixExec() { this = API::moduleImport("webix").getMember("exec").getParameter(0).asSink() } } /** A sink for code injection via template injection. */ @@ -431,15 +431,15 @@ module CodeInjection { */ class WebixTemplateSink extends TemplateSink { WebixTemplateSink() { - this = DataFlow::moduleImport("webix").getAMemberCall("ui").getOptionArgument(0, "template") + this = API::moduleImport("webix").getMember("ui").getParameter(0).getMember("template").asSink() or this.asExpr() = - DataFlow::moduleImport("webix") - .getAMemberCall("ui") - .getOptionArgument(0, "template") - .asExpr() - .(Function) - .getAReturnedExpr() + API::moduleImport("webix") + .getMember("ui") + .getParameter(0) + .getMember("template") + .getReturn() + .asSink() } } From bb67a9000ef672573c30d40db425e77ff03bcfc1 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Mon, 26 Jun 2023 13:32:00 +0200 Subject: [PATCH 08/11] Fix `WebixTemplateSink` --- .../security/dataflow/CodeInjectionCustomizations.qll | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll index d4e62dba6352..fcaabbeaf420 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll @@ -431,9 +431,10 @@ module CodeInjection { */ class WebixTemplateSink extends TemplateSink { WebixTemplateSink() { - this = API::moduleImport("webix").getMember("ui").getParameter(0).getMember("template").asSink() + this = + API::moduleImport("webix").getMember("ui").getParameter(0).getMember("template").asSink() or - this.asExpr() = + this = API::moduleImport("webix") .getMember("ui") .getParameter(0) From 1e663b88895570eb513eefc685378c1abbda8e5e Mon Sep 17 00:00:00 2001 From: jorgectf Date: Mon, 26 Jun 2023 13:32:20 +0200 Subject: [PATCH 09/11] Update `HeuristicSourceCodeInjection.expected` --- .../HeuristicSourceCodeInjection.expected | 134 ++++++++++-------- 1 file changed, 73 insertions(+), 61 deletions(-) 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..729d30019370 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,41 @@ 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 | +| template-sinks.js:34:26:34:32 | tainted | +| template-sinks.js:34:26:34:32 | tainted | +| template-sinks.js:35:47:35:53 | tainted | +| template-sinks.js:35:47:35:53 | 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 +189,9 @@ nodes | tst.js:35:28:35:33 | source | | tst.js:37:33:37:38 | source | | tst.js:37:33:37:38 | source | +| webix.js:3:12:3:33 | documen ... on.hash | +| webix.js:3:12:3:33 | documen ... on.hash | +| webix.js:3:12:3:33 | 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 +261,40 @@ 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:9:18:31 | tainted | template-sinks.js:34:26:34:32 | tainted | +| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:34:26:34:32 | tainted | +| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:35:47:35:53 | tainted | +| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:35:47:35:53 | 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 +325,6 @@ 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.js:3:12:3:33 | documen ... on.hash | webix.js:3:12:3:33 | 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 | From 2ac334bf15399f119a22d5fb5491a11b23ae21b1 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Wed, 28 Jun 2023 15:26:30 +0200 Subject: [PATCH 10/11] Adapt `Webix` modeling to support HTML use-cases --- javascript/ql/lib/javascript.qll | 1 + .../ql/lib/semmle/javascript/Extend.qll | 4 +- .../semmle/javascript/frameworks/Webix.qll | 24 +++++++ .../dataflow/CodeInjectionCustomizations.qll | 12 +--- .../PrototypePollutionCustomizations.qll | 2 +- .../CodeInjection/CodeInjection.expected | 45 ++++++++----- .../HeuristicSourceCodeInjection.expected | 36 ++++++---- .../CWE-094/CodeInjection/template-sinks.js | 2 - .../Security/CWE-094/CodeInjection/webix.js | 3 - .../CWE-094/CodeInjection/webix/webix.html | 6 ++ .../CWE-094/CodeInjection/webix/webix.js | 5 ++ .../PrototypePollutingMergeCall.expected | 66 ++++++++++++------- .../webix/webix.html | 7 ++ .../{ => webix}/webix.js | 0 14 files changed, 148 insertions(+), 65 deletions(-) create mode 100644 javascript/ql/lib/semmle/javascript/frameworks/Webix.qll delete mode 100644 javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/webix.js create mode 100644 javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/webix/webix.html create mode 100644 javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/webix/webix.js create mode 100644 javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/webix/webix.html rename javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/{ => webix}/webix.js (100%) 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 93f59e70c6ab..d0eeade58928 100644 --- a/javascript/ql/lib/semmle/javascript/Extend.qll +++ b/javascript/ql/lib/semmle/javascript/Extend.qll @@ -97,7 +97,9 @@ private class ExtendCallDeep extends ExtendCall { callee = LodashUnderscore::member("mergeWith") or callee = LodashUnderscore::member("defaultsDeep") or callee = AngularJS::angular().getAPropertyRead("merge") or - callee = DataFlow::moduleImport("webix").getAPropertyRead(["extend", "copy"]) + 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..7dc36675ed0e --- /dev/null +++ b/javascript/ql/lib/semmle/javascript/frameworks/Webix.qll @@ -0,0 +1,24 @@ +/** + * 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.asSource() = DataFlow::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 fcaabbeaf420..ce05747ec3f2 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll @@ -316,7 +316,7 @@ module CodeInjection { * A value interpreted as code by the `webix` library. */ class WebixExec extends Sink { - WebixExec() { this = API::moduleImport("webix").getMember("exec").getParameter(0).asSink() } + WebixExec() { this = Webix::webix().getMember("exec").getParameter(0).asSink() } } /** A sink for code injection via template injection. */ @@ -431,16 +431,10 @@ module CodeInjection { */ class WebixTemplateSink extends TemplateSink { WebixTemplateSink() { - this = - API::moduleImport("webix").getMember("ui").getParameter(0).getMember("template").asSink() + this = Webix::webix().getMember("ui").getParameter(0).getMember("template").asSink() or this = - API::moduleImport("webix") - .getMember("ui") - .getParameter(0) - .getMember("template") - .getReturn() - .asSink() + Webix::webix().getMember("ui").getParameter(0).getMember("template").getReturn().asSink() } } diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionCustomizations.qll index e3cce57add61..fdd1b5c1c881 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionCustomizations.qll @@ -173,7 +173,7 @@ module PrototypePollution { id = "angular" or call.isDeep() and - call = DataFlow::moduleImport("webix").getAMemberCall(["extend", "copy"]) 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 cc3175a3645c..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 @@ -143,10 +143,6 @@ nodes | template-sinks.js:32:16:32:22 | tainted | | template-sinks.js:33:17:33:23 | tainted | | template-sinks.js:33:17:33:23 | tainted | -| template-sinks.js:34:26:34:32 | tainted | -| template-sinks.js:34:26:34:32 | tainted | -| template-sinks.js:35:47:35:53 | tainted | -| template-sinks.js:35:47:35:53 | 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,9 +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.js:3:12:3:33 | documen ... on.hash | -| webix.js:3:12:3:33 | documen ... on.hash | -| webix.js:3:12:3:33 | 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: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 | @@ -281,10 +292,6 @@ edges | 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:9:18:31 | tainted | template-sinks.js:34:26:34:32 | tainted | -| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:34:26:34:32 | tainted | -| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:35:47:35:53 | tainted | -| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:35:47:35:53 | 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) | @@ -317,7 +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.js:3:12:3:33 | documen ... on.hash | webix.js:3:12:3:33 | 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: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 | @@ -366,8 +378,6 @@ edges | 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 | -| template-sinks.js:34:26:34:32 | tainted | template-sinks.js:18:19:18:31 | req.query.foo | template-sinks.js:34:26:34:32 | 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:35:47:35:53 | tainted | template-sinks.js:18:19:18:31 | req.query.foo | template-sinks.js:35:47:35:53 | 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 | @@ -379,4 +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.js:3:12:3:33 | documen ... on.hash | webix.js:3:12:3:33 | documen ... on.hash | webix.js:3:12:3:33 | documen ... on.hash | This code execution depends on a $@. | webix.js:3:12:3:33 | documen ... on.hash | 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 729d30019370..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 @@ -147,10 +147,6 @@ nodes | template-sinks.js:32:16:32:22 | tainted | | template-sinks.js:33:17:33:23 | tainted | | template-sinks.js:33:17:33:23 | tainted | -| template-sinks.js:34:26:34:32 | tainted | -| template-sinks.js:34:26:34:32 | tainted | -| template-sinks.js:35:47:35:53 | tainted | -| template-sinks.js:35:47:35:53 | 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) | @@ -189,9 +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.js:3:12:3:33 | documen ... on.hash | -| webix.js:3:12:3:33 | documen ... on.hash | -| webix.js:3:12:3:33 | 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: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 | @@ -289,10 +300,6 @@ edges | 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:9:18:31 | tainted | template-sinks.js:34:26:34:32 | tainted | -| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:34:26:34:32 | tainted | -| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:35:47:35:53 | tainted | -| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:35:47:35:53 | 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) | @@ -325,6 +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.js:3:12:3:33 | documen ... on.hash | webix.js:3:12:3:33 | 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: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 5b786cdeee40..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 @@ -31,6 +31,4 @@ app.get('/some/path', function (req, res) { Hogan.compile(tainted); // NOT OK Eta.render(tainted); // NOT OK Sqrl.render(tainted); // NOT OK - webix.ui({ template: tainted }); // NOT OK - webix.ui({ template: function () { return tainted } }); // NOT OK }); diff --git a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/webix.js b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/webix.js deleted file mode 100644 index 289bffe22b47..000000000000 --- a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/webix.js +++ /dev/null @@ -1,3 +0,0 @@ -import * as webix from 'webix'; - -webix.exec(document.location.hash); // NOT OK \ No newline at end of file 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 0699ba81815d..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,16 +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.js:3:30:3:34 | event | -| webix.js:3:30:3:34 | event | -| webix.js:4:22:4:43 | JSON.pa ... t.data) | -| webix.js:4:22:4:43 | JSON.pa ... t.data) | -| webix.js:4:33:4:37 | event | -| webix.js:4:33:4:42 | event.data | -| webix.js:5:19:5:40 | JSON.pa ... t.data) | -| webix.js:5:19:5:40 | JSON.pa ... t.data) | -| webix.js:5:30:5:34 | event | -| webix.js:5:30:5:39 | event.data | +| 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 | @@ -42,20 +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.js:3:30:3:34 | event | webix.js:4:33:4:37 | event | -| webix.js:3:30:3:34 | event | webix.js:4:33:4:37 | event | -| webix.js:3:30:3:34 | event | webix.js:5:30:5:34 | event | -| webix.js:3:30:3:34 | event | webix.js:5:30:5:34 | event | -| webix.js:4:33:4:37 | event | webix.js:4:33:4:42 | event.data | -| webix.js:4:33:4:42 | event.data | webix.js:4:22:4:43 | JSON.pa ... t.data) | -| webix.js:4:33:4:42 | event.data | webix.js:4:22:4:43 | JSON.pa ... t.data) | -| webix.js:5:30:5:34 | event | webix.js:5:30:5:39 | event.data | -| webix.js:5:30:5:39 | event.data | webix.js:5:19:5:40 | JSON.pa ... t.data) | -| webix.js:5:30:5:39 | event.data | webix.js:5:19:5:40 | JSON.pa ... t.data) | +| 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.js:4:22:4:43 | JSON.pa ... t.data) | webix.js:3:30:3:34 | event | webix.js:4:22:4:43 | JSON.pa ... t.data) | Prototype pollution caused by merging a $@ using a vulnerable version of $@. | webix.js:3:30:3:34 | event | user-controlled value | webix.js:4:5:4:44 | webix.e ... .data)) | webix | -| webix.js:5:19:5:40 | JSON.pa ... t.data) | webix.js:3:30:3:34 | event | webix.js:5:19:5:40 | JSON.pa ... t.data) | Prototype pollution caused by merging a $@ using a vulnerable version of $@. | webix.js:3:30:3:34 | event | user-controlled value | webix.js:5:5:5:41 | webix.c ... .data)) | webix | +| 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.js b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/webix/webix.js similarity index 100% rename from javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/webix.js rename to javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/webix/webix.js From e210b0d0a7ad8df9fb792b38533bfff7828c48f0 Mon Sep 17 00:00:00 2001 From: Jorge <46056498+jorgectf@users.noreply.github.com> Date: Thu, 29 Jun 2023 16:06:34 +0200 Subject: [PATCH 11/11] Apply suggestions from code review Co-authored-by: Asger F --- javascript/ql/lib/semmle/javascript/frameworks/Webix.qll | 1 - 1 file changed, 1 deletion(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Webix.qll b/javascript/ql/lib/semmle/javascript/frameworks/Webix.qll index 7dc36675ed0e..effd49c632bf 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Webix.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Webix.qll @@ -18,7 +18,6 @@ module Webix { /** Gets a reference to the Webix package. */ API::Node webix() { result = API::moduleImport("webix") or - result.asSource() = DataFlow::moduleImport("webix") or result = any(WebixGlobalEntry w).getANode() } }