Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions javascript/ql/lib/change-notes/2023-06-22-webix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Added models for the Webix Framework.
1 change: 1 addition & 0 deletions javascript/ql/lib/javascript.qll
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 4 additions & 1 deletion javascript/ql/lib/semmle/javascript/Extend.qll
Original file line number Diff line number Diff line change
Expand Up @@ -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"])
)
}

Expand Down
23 changes: 23 additions & 0 deletions javascript/ql/lib/semmle/javascript/frameworks/Webix.qll
Original file line number Diff line number Diff line change
@@ -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()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -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) |
Expand Down Expand Up @@ -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 |
Expand Down Expand Up @@ -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) |
Expand Down Expand Up @@ -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 |
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<script src="path/to/webix.js" type="text/javascript" charset="utf-8"></script>
<script>
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
</script>
Original file line number Diff line number Diff line change
@@ -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
Loading