Skip to content

Commit 4c9501e

Browse files
authored
Merge pull request github#13529 from jorgectf/seclab/webix-modeling
JS: Add models for `webix`
2 parents 95ddc01 + e210b0d commit 4c9501e

File tree

14 files changed

+315
-138
lines changed

14 files changed

+315
-138
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* Added models for the Webix Framework.

javascript/ql/lib/javascript.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ import semmle.javascript.frameworks.TrustedTypes
134134
import semmle.javascript.frameworks.UriLibraries
135135
import semmle.javascript.frameworks.Vue
136136
import semmle.javascript.frameworks.Vuex
137+
import semmle.javascript.frameworks.Webix
137138
import semmle.javascript.frameworks.WebSocket
138139
import semmle.javascript.frameworks.XmlParsers
139140
import semmle.javascript.frameworks.xUnit

javascript/ql/lib/semmle/javascript/Extend.qll

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,10 @@ private class ExtendCallDeep extends ExtendCall {
9696
callee = LodashUnderscore::member("merge") or
9797
callee = LodashUnderscore::member("mergeWith") or
9898
callee = LodashUnderscore::member("defaultsDeep") or
99-
callee = AngularJS::angular().getAPropertyRead("merge")
99+
callee = AngularJS::angular().getAPropertyRead("merge") or
100+
callee =
101+
[DataFlow::moduleImport("webix"), DataFlow::globalVarRef("webix")]
102+
.getAPropertyRead(["extend", "copy"])
100103
)
101104
}
102105

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/**
2+
* Provides classes and predicates for working with the `webix` library.
3+
*/
4+
5+
private import javascript
6+
7+
/**
8+
* Provides classes and predicates for working with the `webix` library.
9+
*/
10+
module Webix {
11+
/** The global variable `webix` as an entry point for API graphs. */
12+
private class WebixGlobalEntry extends API::EntryPoint {
13+
WebixGlobalEntry() { this = "WebixGlobalEntry" }
14+
15+
override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef("webix") }
16+
}
17+
18+
/** Gets a reference to the Webix package. */
19+
API::Node webix() {
20+
result = API::moduleImport("webix") or
21+
result = any(WebixGlobalEntry w).getANode()
22+
}
23+
}

javascript/ql/lib/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,13 @@ module CodeInjection {
312312
}
313313
}
314314

315+
/**
316+
* A value interpreted as code by the `webix` library.
317+
*/
318+
class WebixExec extends Sink {
319+
WebixExec() { this = Webix::webix().getMember("exec").getParameter(0).asSink() }
320+
}
321+
315322
/** A sink for code injection via template injection. */
316323
abstract private class TemplateSink extends Sink {
317324
deprecated override string getMessageSuffix() {
@@ -419,6 +426,18 @@ module CodeInjection {
419426
}
420427
}
421428

429+
/**
430+
* A value interpreted as a template by the `webix` library.
431+
*/
432+
class WebixTemplateSink extends TemplateSink {
433+
WebixTemplateSink() {
434+
this = Webix::webix().getMember("ui").getParameter(0).getMember("template").asSink()
435+
or
436+
this =
437+
Webix::webix().getMember("ui").getParameter(0).getMember("template").getReturn().asSink()
438+
}
439+
}
440+
422441
/**
423442
* A call to JSON.stringify() seen as a sanitizer.
424443
*/

javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionCustomizations.qll

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,5 +171,9 @@ module PrototypePollution {
171171
call.isDeep() and
172172
call = AngularJS::angular().getAMemberCall("merge") and
173173
id = "angular"
174+
or
175+
call.isDeep() and
176+
call = Webix::webix().getMember(["extend", "copy"]).getACall() and
177+
id = "webix"
174178
}
175179
}

javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected

Lines changed: 105 additions & 75 deletions
Large diffs are not rendered by default.

javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/HeuristicSourceCodeInjection.expected

Lines changed: 85 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -116,37 +116,37 @@ nodes
116116
| react.js:10:56:10:77 | documen ... on.hash |
117117
| react.js:10:56:10:77 | documen ... on.hash |
118118
| react.js:10:56:10:77 | documen ... on.hash |
119-
| template-sinks.js:17:9:17:31 | tainted |
120-
| template-sinks.js:17:19:17:31 | req.query.foo |
121-
| template-sinks.js:17:19:17:31 | req.query.foo |
122-
| template-sinks.js:19:17:19:23 | tainted |
123-
| template-sinks.js:19:17:19:23 | tainted |
124-
| template-sinks.js:20:16:20:22 | tainted |
125-
| template-sinks.js:20:16:20:22 | tainted |
126-
| template-sinks.js:21:18:21:24 | tainted |
127-
| template-sinks.js:21:18:21:24 | tainted |
128-
| template-sinks.js:22:17:22:23 | tainted |
129-
| template-sinks.js:22:17:22:23 | tainted |
130-
| template-sinks.js:23:18:23:24 | tainted |
131-
| template-sinks.js:23:18:23:24 | tainted |
132-
| template-sinks.js:24:16:24:22 | tainted |
133-
| template-sinks.js:24:16:24:22 | tainted |
134-
| template-sinks.js:25:27:25:33 | tainted |
135-
| template-sinks.js:25:27:25:33 | tainted |
136-
| template-sinks.js:26:21:26:27 | tainted |
137-
| template-sinks.js:26:21:26:27 | tainted |
138-
| template-sinks.js:27:17:27:23 | tainted |
139-
| template-sinks.js:27:17:27:23 | tainted |
140-
| template-sinks.js:28:24:28:30 | tainted |
141-
| template-sinks.js:28:24:28:30 | tainted |
142-
| template-sinks.js:29:21:29:27 | tainted |
143-
| template-sinks.js:29:21:29:27 | tainted |
144-
| template-sinks.js:30:19:30:25 | tainted |
145-
| template-sinks.js:30:19:30:25 | tainted |
146-
| template-sinks.js:31:16:31:22 | tainted |
147-
| template-sinks.js:31:16:31:22 | tainted |
148-
| template-sinks.js:32:17:32:23 | tainted |
149-
| template-sinks.js:32:17:32:23 | tainted |
119+
| template-sinks.js:18:9:18:31 | tainted |
120+
| template-sinks.js:18:19:18:31 | req.query.foo |
121+
| template-sinks.js:18:19:18:31 | req.query.foo |
122+
| template-sinks.js:20:17:20:23 | tainted |
123+
| template-sinks.js:20:17:20:23 | tainted |
124+
| template-sinks.js:21:16:21:22 | tainted |
125+
| template-sinks.js:21:16:21:22 | tainted |
126+
| template-sinks.js:22:18:22:24 | tainted |
127+
| template-sinks.js:22:18:22:24 | tainted |
128+
| template-sinks.js:23:17:23:23 | tainted |
129+
| template-sinks.js:23:17:23:23 | tainted |
130+
| template-sinks.js:24:18:24:24 | tainted |
131+
| template-sinks.js:24:18:24:24 | tainted |
132+
| template-sinks.js:25:16:25:22 | tainted |
133+
| template-sinks.js:25:16:25:22 | tainted |
134+
| template-sinks.js:26:27:26:33 | tainted |
135+
| template-sinks.js:26:27:26:33 | tainted |
136+
| template-sinks.js:27:21:27:27 | tainted |
137+
| template-sinks.js:27:21:27:27 | tainted |
138+
| template-sinks.js:28:17:28:23 | tainted |
139+
| template-sinks.js:28:17:28:23 | tainted |
140+
| template-sinks.js:29:24:29:30 | tainted |
141+
| template-sinks.js:29:24:29:30 | tainted |
142+
| template-sinks.js:30:21:30:27 | tainted |
143+
| template-sinks.js:30:21:30:27 | tainted |
144+
| template-sinks.js:31:19:31:25 | tainted |
145+
| template-sinks.js:31:19:31:25 | tainted |
146+
| template-sinks.js:32:16:32:22 | tainted |
147+
| template-sinks.js:32:16:32:22 | tainted |
148+
| template-sinks.js:33:17:33:23 | tainted |
149+
| template-sinks.js:33:17:33:23 | tainted |
150150
| tst.js:2:6:2:27 | documen ... on.href |
151151
| tst.js:2:6:2:27 | documen ... on.href |
152152
| tst.js:2:6:2:83 | documen ... t=")+8) |
@@ -185,6 +185,24 @@ nodes
185185
| tst.js:35:28:35:33 | source |
186186
| tst.js:37:33:37:38 | source |
187187
| tst.js:37:33:37:38 | source |
188+
| webix/webix.html:3:16:3:37 | documen ... on.hash |
189+
| webix/webix.html:3:16:3:37 | documen ... on.hash |
190+
| webix/webix.html:3:16:3:37 | documen ... on.hash |
191+
| webix/webix.html:4:26:4:47 | documen ... on.hash |
192+
| webix/webix.html:4:26:4:47 | documen ... on.hash |
193+
| webix/webix.html:4:26:4:47 | documen ... on.hash |
194+
| webix/webix.html:5:47:5:68 | documen ... on.hash |
195+
| webix/webix.html:5:47:5:68 | documen ... on.hash |
196+
| webix/webix.html:5:47:5:68 | documen ... on.hash |
197+
| webix/webix.js:3:12:3:33 | documen ... on.hash |
198+
| webix/webix.js:3:12:3:33 | documen ... on.hash |
199+
| webix/webix.js:3:12:3:33 | documen ... on.hash |
200+
| webix/webix.js:4:22:4:43 | documen ... on.hash |
201+
| webix/webix.js:4:22:4:43 | documen ... on.hash |
202+
| webix/webix.js:4:22:4:43 | documen ... on.hash |
203+
| webix/webix.js:5:43:5:64 | documen ... on.hash |
204+
| webix/webix.js:5:43:5:64 | documen ... on.hash |
205+
| webix/webix.js:5:43:5:64 | documen ... on.hash |
188206
edges
189207
| NoSQLCodeInjection.js:18:24:18:31 | req.body | NoSQLCodeInjection.js:18:24:18:37 | req.body.query |
190208
| NoSQLCodeInjection.js:18:24:18:31 | req.body | NoSQLCodeInjection.js:18:24:18:37 | req.body.query |
@@ -254,36 +272,36 @@ edges
254272
| react-native.js:7:17:7:33 | req.param("code") | react-native.js:7:7:7:33 | tainted |
255273
| react-native.js:7:17:7:33 | req.param("code") | react-native.js:7:7:7:33 | tainted |
256274
| react.js:10:56:10:77 | documen ... on.hash | react.js:10:56:10:77 | documen ... on.hash |
257-
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:19:17:19:23 | tainted |
258-
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:19:17:19:23 | tainted |
259-
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:20:16:20:22 | tainted |
260-
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:20:16:20:22 | tainted |
261-
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:21:18:21:24 | tainted |
262-
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:21:18:21:24 | tainted |
263-
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:22:17:22:23 | tainted |
264-
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:22:17:22:23 | tainted |
265-
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:23:18:23:24 | tainted |
266-
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:23:18:23:24 | tainted |
267-
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:24:16:24:22 | tainted |
268-
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:24:16:24:22 | tainted |
269-
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:25:27:25:33 | tainted |
270-
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:25:27:25:33 | tainted |
271-
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:26:21:26:27 | tainted |
272-
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:26:21:26:27 | tainted |
273-
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:27:17:27:23 | tainted |
274-
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:27:17:27:23 | tainted |
275-
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:28:24:28:30 | tainted |
276-
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:28:24:28:30 | tainted |
277-
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:29:21:29:27 | tainted |
278-
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:29:21:29:27 | tainted |
279-
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:30:19:30:25 | tainted |
280-
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:30:19:30:25 | tainted |
281-
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:31:16:31:22 | tainted |
282-
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:31:16:31:22 | tainted |
283-
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:32:17:32:23 | tainted |
284-
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:32:17:32:23 | tainted |
285-
| template-sinks.js:17:19:17:31 | req.query.foo | template-sinks.js:17:9:17:31 | tainted |
286-
| template-sinks.js:17:19:17:31 | req.query.foo | template-sinks.js:17:9:17:31 | tainted |
275+
| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:20:17:20:23 | tainted |
276+
| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:20:17:20:23 | tainted |
277+
| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:21:16:21:22 | tainted |
278+
| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:21:16:21:22 | tainted |
279+
| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:22:18:22:24 | tainted |
280+
| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:22:18:22:24 | tainted |
281+
| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:23:17:23:23 | tainted |
282+
| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:23:17:23:23 | tainted |
283+
| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:24:18:24:24 | tainted |
284+
| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:24:18:24:24 | tainted |
285+
| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:25:16:25:22 | tainted |
286+
| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:25:16:25:22 | tainted |
287+
| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:26:27:26:33 | tainted |
288+
| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:26:27:26:33 | tainted |
289+
| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:27:21:27:27 | tainted |
290+
| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:27:21:27:27 | tainted |
291+
| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:28:17:28:23 | tainted |
292+
| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:28:17:28:23 | tainted |
293+
| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:29:24:29:30 | tainted |
294+
| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:29:24:29:30 | tainted |
295+
| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:30:21:30:27 | tainted |
296+
| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:30:21:30:27 | tainted |
297+
| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:31:19:31:25 | tainted |
298+
| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:31:19:31:25 | tainted |
299+
| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:32:16:32:22 | tainted |
300+
| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:32:16:32:22 | tainted |
301+
| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:33:17:33:23 | tainted |
302+
| template-sinks.js:18:9:18:31 | tainted | template-sinks.js:33:17:33:23 | tainted |
303+
| template-sinks.js:18:19:18:31 | req.query.foo | template-sinks.js:18:9:18:31 | tainted |
304+
| template-sinks.js:18:19:18:31 | req.query.foo | template-sinks.js:18:9:18:31 | tainted |
287305
| tst.js:2:6:2:27 | documen ... on.href | tst.js:2:6:2:83 | documen ... t=")+8) |
288306
| tst.js:2:6:2:27 | documen ... on.href | tst.js:2:6:2:83 | documen ... t=")+8) |
289307
| tst.js:2:6:2:27 | documen ... on.href | tst.js:2:6:2:83 | documen ... t=")+8) |
@@ -314,5 +332,11 @@ edges
314332
| tst.js:29:18:29:41 | documen ... .search | tst.js:29:18:29:82 | documen ... , "$1") |
315333
| tst.js:29:18:29:41 | documen ... .search | tst.js:29:18:29:82 | documen ... , "$1") |
316334
| tst.js:29:18:29:82 | documen ... , "$1") | tst.js:29:9:29:82 | source |
335+
| webix/webix.html:3:16:3:37 | documen ... on.hash | webix/webix.html:3:16:3:37 | documen ... on.hash |
336+
| webix/webix.html:4:26:4:47 | documen ... on.hash | webix/webix.html:4:26:4:47 | documen ... on.hash |
337+
| webix/webix.html:5:47:5:68 | documen ... on.hash | webix/webix.html:5:47:5:68 | documen ... on.hash |
338+
| webix/webix.js:3:12:3:33 | documen ... on.hash | webix/webix.js:3:12:3:33 | documen ... on.hash |
339+
| webix/webix.js:4:22:4:43 | documen ... on.hash | webix/webix.js:4:22:4:43 | documen ... on.hash |
340+
| webix/webix.js:5:43:5:64 | documen ... on.hash | webix/webix.js:5:43:5:64 | documen ... on.hash |
317341
#select
318342
| 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 |

javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/template-sinks.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@ import * as mustache from 'mustache';
1010
const Hogan = require("hogan.js");
1111
import * as Eta from 'eta';
1212
import * as Sqrl from 'squirrelly'
13+
import * as webix from "webix";
1314

1415
var app = express();
1516

16-
app.get('/some/path', function(req, res) {
17+
app.get('/some/path', function (req, res) {
1718
let tainted = req.query.foo;
1819

1920
pug.compile(tainted); // NOT OK
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<script src="path/to/webix.js" type="text/javascript" charset="utf-8"></script>
2+
<script>
3+
webix.exec(document.location.hash); // NOT OK
4+
webix.ui({ template: document.location.hash }); // NOT OK
5+
webix.ui({ template: function () { return document.location.hash } }); // NOT OK
6+
</script>

0 commit comments

Comments
 (0)