Skip to content

Commit b66f4cb

Browse files
authored
Merge pull request github#6134 from erik-krogh/templates
Approved by asgerf, esbena
2 parents 2dc0849 + 2ba2642 commit b66f4cb

File tree

5 files changed

+211
-84
lines changed

5 files changed

+211
-84
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
lgtm,codescanning
2+
* More template engines are recognized as sinks for the `js/code-injection` query.
3+
Affected packages are
4+
[mustache](https://npmjs.com/package/mustache),
5+
[handlebars](https://npmjs.com/package/handlebars),
6+
[dot](https://npmjs.com/package/dot),
7+
[hogan.js](https://npmjs.com/package/hogan.js)
8+
[eta](https://npmjs.com/package/eta),
9+
[squirrelly](https://npmjs.com/package/squirrelly),
10+
[whiskers](https://npmjs.com/package/whiskers)

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

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,11 +197,63 @@ module CodeInjection {
197197
}
198198

199199
/**
200-
* A value interpreted as a tempalte by the `dot` library.
200+
* A value interpreted as a template by the `handlebars` library.
201+
*/
202+
class HandlebarsTemplateSink extends TemplateSink {
203+
HandlebarsTemplateSink() {
204+
this = any(Handlebars::Handlebars h).getAMemberCall("compile").getArgument(0)
205+
}
206+
}
207+
208+
/**
209+
* A value interpreted as a template by the `mustache` library.
210+
*/
211+
class MustacheTemplateSink extends TemplateSink {
212+
MustacheTemplateSink() {
213+
this = DataFlow::moduleMember("mustache", "render").getACall().getArgument(0)
214+
}
215+
}
216+
217+
/**
218+
* A value interpreted as a template by the `hogan.js` library.
219+
*/
220+
class HoganTemplateSink extends TemplateSink {
221+
HoganTemplateSink() {
222+
this = DataFlow::moduleMember("hogan.js", "compile").getACall().getArgument(0)
223+
}
224+
}
225+
226+
/**
227+
* A value interpreted as a template by the `eta` library.
228+
*/
229+
class EtaTemplateSink extends TemplateSink {
230+
EtaTemplateSink() { this = DataFlow::moduleMember("eta", "render").getACall().getArgument(0) }
231+
}
232+
233+
/**
234+
* A value interpreted as a template by the `squirrelly` library.
235+
*/
236+
class SquirrelTemplateSink extends TemplateSink {
237+
SquirrelTemplateSink() {
238+
this = DataFlow::moduleMember("squirrelly", "render").getACall().getArgument(0)
239+
}
240+
}
241+
242+
/**
243+
* A value interpreted as a template by the `whiskers` library.
244+
*/
245+
class WhiskersTemplateSink extends TemplateSink {
246+
WhiskersTemplateSink() {
247+
this = DataFlow::moduleMember("whiskers", "render").getACall().getArgument(0)
248+
}
249+
}
250+
251+
/**
252+
* A value interpreted as a template by the `dot` library.
201253
*/
202254
class DotTemplateSink extends TemplateSink {
203255
DotTemplateSink() {
204-
this = DataFlow::moduleImport("dot").getAMemberCall("template").getArgument(0)
256+
this = DataFlow::moduleImport("dot").getAMemberCall(["template", "compile"]).getArgument(0)
205257
}
206258
}
207259

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

Lines changed: 75 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -107,25 +107,37 @@ nodes
107107
| react.js:10:56:10:77 | documen ... on.hash |
108108
| react.js:10:56:10:77 | documen ... on.hash |
109109
| react.js:10:56:10:77 | documen ... on.hash |
110-
| template-sinks.js:12:9:12:31 | tainted |
111-
| template-sinks.js:12:19:12:31 | req.query.foo |
112-
| template-sinks.js:12:19:12:31 | req.query.foo |
113-
| template-sinks.js:14:17:14:23 | tainted |
114-
| template-sinks.js:14:17:14:23 | tainted |
115-
| template-sinks.js:15:16:15:22 | tainted |
116-
| template-sinks.js:15:16:15:22 | tainted |
117-
| template-sinks.js:16:18:16:24 | tainted |
118-
| template-sinks.js:16:18:16:24 | tainted |
119-
| template-sinks.js:17:17:17:23 | tainted |
120-
| template-sinks.js:17:17:17:23 | tainted |
121-
| template-sinks.js:18:18:18:24 | tainted |
122-
| template-sinks.js:18:18:18:24 | tainted |
123-
| template-sinks.js:19:16:19:22 | tainted |
124-
| template-sinks.js:19:16:19:22 | tainted |
125-
| template-sinks.js:20:27:20:33 | tainted |
126-
| template-sinks.js:20:27:20:33 | tainted |
127-
| template-sinks.js:21:21:21:27 | tainted |
128-
| template-sinks.js:21:21:21:27 | tainted |
110+
| template-sinks.js:17:9:17:31 | tainted |
111+
| template-sinks.js:17:19:17:31 | req.query.foo |
112+
| template-sinks.js:17:19:17:31 | req.query.foo |
113+
| template-sinks.js:19:17:19:23 | tainted |
114+
| template-sinks.js:19:17:19:23 | tainted |
115+
| template-sinks.js:20:16:20:22 | tainted |
116+
| template-sinks.js:20:16:20:22 | tainted |
117+
| template-sinks.js:21:18:21:24 | tainted |
118+
| template-sinks.js:21:18:21:24 | tainted |
119+
| template-sinks.js:22:17:22:23 | tainted |
120+
| template-sinks.js:22:17:22:23 | tainted |
121+
| template-sinks.js:23:18:23:24 | tainted |
122+
| template-sinks.js:23:18:23:24 | tainted |
123+
| template-sinks.js:24:16:24:22 | tainted |
124+
| template-sinks.js:24:16:24:22 | tainted |
125+
| template-sinks.js:25:27:25:33 | tainted |
126+
| template-sinks.js:25:27:25:33 | tainted |
127+
| template-sinks.js:26:21:26:27 | tainted |
128+
| template-sinks.js:26:21:26:27 | tainted |
129+
| template-sinks.js:27:17:27:23 | tainted |
130+
| template-sinks.js:27:17:27:23 | tainted |
131+
| template-sinks.js:28:24:28:30 | tainted |
132+
| template-sinks.js:28:24:28:30 | tainted |
133+
| template-sinks.js:29:21:29:27 | tainted |
134+
| template-sinks.js:29:21:29:27 | tainted |
135+
| template-sinks.js:30:19:30:25 | tainted |
136+
| template-sinks.js:30:19:30:25 | tainted |
137+
| template-sinks.js:31:16:31:22 | tainted |
138+
| template-sinks.js:31:16:31:22 | tainted |
139+
| template-sinks.js:32:17:32:23 | tainted |
140+
| template-sinks.js:32:17:32:23 | tainted |
129141
| tst.js:2:6:2:27 | documen ... on.href |
130142
| tst.js:2:6:2:27 | documen ... on.href |
131143
| tst.js:2:6:2:83 | documen ... t=")+8) |
@@ -216,24 +228,36 @@ edges
216228
| react-native.js:7:17:7:33 | req.param("code") | react-native.js:7:7:7:33 | tainted |
217229
| react-native.js:7:17:7:33 | req.param("code") | react-native.js:7:7:7:33 | tainted |
218230
| react.js:10:56:10:77 | documen ... on.hash | react.js:10:56:10:77 | documen ... on.hash |
219-
| template-sinks.js:12:9:12:31 | tainted | template-sinks.js:14:17:14:23 | tainted |
220-
| template-sinks.js:12:9:12:31 | tainted | template-sinks.js:14:17:14:23 | tainted |
221-
| template-sinks.js:12:9:12:31 | tainted | template-sinks.js:15:16:15:22 | tainted |
222-
| template-sinks.js:12:9:12:31 | tainted | template-sinks.js:15:16:15:22 | tainted |
223-
| template-sinks.js:12:9:12:31 | tainted | template-sinks.js:16:18:16:24 | tainted |
224-
| template-sinks.js:12:9:12:31 | tainted | template-sinks.js:16:18:16:24 | tainted |
225-
| template-sinks.js:12:9:12:31 | tainted | template-sinks.js:17:17:17:23 | tainted |
226-
| template-sinks.js:12:9:12:31 | tainted | template-sinks.js:17:17:17:23 | tainted |
227-
| template-sinks.js:12:9:12:31 | tainted | template-sinks.js:18:18:18:24 | tainted |
228-
| template-sinks.js:12:9:12:31 | tainted | template-sinks.js:18:18:18:24 | tainted |
229-
| template-sinks.js:12:9:12:31 | tainted | template-sinks.js:19:16:19:22 | tainted |
230-
| template-sinks.js:12:9:12:31 | tainted | template-sinks.js:19:16:19:22 | tainted |
231-
| template-sinks.js:12:9:12:31 | tainted | template-sinks.js:20:27:20:33 | tainted |
232-
| template-sinks.js:12:9:12:31 | tainted | template-sinks.js:20:27:20:33 | tainted |
233-
| template-sinks.js:12:9:12:31 | tainted | template-sinks.js:21:21:21:27 | tainted |
234-
| template-sinks.js:12:9:12:31 | tainted | template-sinks.js:21:21:21:27 | tainted |
235-
| template-sinks.js:12:19:12:31 | req.query.foo | template-sinks.js:12:9:12:31 | tainted |
236-
| template-sinks.js:12:19:12:31 | req.query.foo | template-sinks.js:12:9:12:31 | tainted |
231+
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:19:17:19:23 | tainted |
232+
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:19:17:19:23 | tainted |
233+
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:20:16:20:22 | tainted |
234+
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:20:16:20:22 | tainted |
235+
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:21:18:21:24 | tainted |
236+
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:21:18:21:24 | tainted |
237+
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:22:17:22:23 | tainted |
238+
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:22:17:22:23 | tainted |
239+
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:23:18:23:24 | tainted |
240+
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:23:18:23:24 | tainted |
241+
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:24:16:24:22 | tainted |
242+
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:24:16:24:22 | tainted |
243+
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:25:27:25:33 | tainted |
244+
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:25:27:25:33 | tainted |
245+
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:26:21:26:27 | tainted |
246+
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:26:21:26:27 | tainted |
247+
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:27:17:27:23 | tainted |
248+
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:27:17:27:23 | tainted |
249+
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:28:24:28:30 | tainted |
250+
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:28:24:28:30 | tainted |
251+
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:29:21:29:27 | tainted |
252+
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:29:21:29:27 | tainted |
253+
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:30:19:30:25 | tainted |
254+
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:30:19:30:25 | tainted |
255+
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:31:16:31:22 | tainted |
256+
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:31:16:31:22 | tainted |
257+
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:32:17:32:23 | tainted |
258+
| template-sinks.js:17:9:17:31 | tainted | template-sinks.js:32:17:32:23 | tainted |
259+
| template-sinks.js:17:19:17:31 | req.query.foo | template-sinks.js:17:9:17:31 | tainted |
260+
| template-sinks.js:17:19:17:31 | req.query.foo | template-sinks.js:17:9:17:31 | tainted |
237261
| tst.js:2:6:2:27 | documen ... on.href | tst.js:2:6:2:83 | documen ... t=")+8) |
238262
| tst.js:2:6:2:27 | documen ... on.href | tst.js:2:6:2:83 | documen ... t=")+8) |
239263
| tst.js:2:6:2:27 | documen ... on.href | tst.js:2:6:2:83 | documen ... t=")+8) |
@@ -284,14 +308,20 @@ edges
284308
| 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 | $@ flows to here and is interpreted as code. | react-native.js:7:17:7:33 | req.param("code") | User-provided value |
285309
| 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 | $@ flows to here and is interpreted as code. | react-native.js:7:17:7:33 | req.param("code") | User-provided value |
286310
| 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 | $@ flows to here and is interpreted as code. | react.js:10:56:10:77 | documen ... on.hash | User-provided value |
287-
| template-sinks.js:14:17:14:23 | tainted | template-sinks.js:12:19:12:31 | req.query.foo | template-sinks.js:14:17:14:23 | tainted | $@ flows to here and is interpreted as a template, which may contain code. | template-sinks.js:12:19:12:31 | req.query.foo | User-provided value |
288-
| template-sinks.js:15:16:15:22 | tainted | template-sinks.js:12:19:12:31 | req.query.foo | template-sinks.js:15:16:15:22 | tainted | $@ flows to here and is interpreted as a template, which may contain code. | template-sinks.js:12:19:12:31 | req.query.foo | User-provided value |
289-
| template-sinks.js:16:18:16:24 | tainted | template-sinks.js:12:19:12:31 | req.query.foo | template-sinks.js:16:18:16:24 | tainted | $@ flows to here and is interpreted as a template, which may contain code. | template-sinks.js:12:19:12:31 | req.query.foo | User-provided value |
290-
| template-sinks.js:17:17:17:23 | tainted | template-sinks.js:12:19:12:31 | req.query.foo | template-sinks.js:17:17:17:23 | tainted | $@ flows to here and is interpreted as a template, which may contain code. | template-sinks.js:12:19:12:31 | req.query.foo | User-provided value |
291-
| template-sinks.js:18:18:18:24 | tainted | template-sinks.js:12:19:12:31 | req.query.foo | template-sinks.js:18:18:18:24 | tainted | $@ flows to here and is interpreted as a template, which may contain code. | template-sinks.js:12:19:12:31 | req.query.foo | User-provided value |
292-
| template-sinks.js:19:16:19:22 | tainted | template-sinks.js:12:19:12:31 | req.query.foo | template-sinks.js:19:16:19:22 | tainted | $@ flows to here and is interpreted as a template, which may contain code. | template-sinks.js:12:19:12:31 | req.query.foo | User-provided value |
293-
| template-sinks.js:20:27:20:33 | tainted | template-sinks.js:12:19:12:31 | req.query.foo | template-sinks.js:20:27:20:33 | tainted | $@ flows to here and is interpreted as a template, which may contain code. | template-sinks.js:12:19:12:31 | req.query.foo | User-provided value |
294-
| template-sinks.js:21:21:21:27 | tainted | template-sinks.js:12:19:12:31 | req.query.foo | template-sinks.js:21:21:21:27 | tainted | $@ flows to here and is interpreted as a template, which may contain code. | template-sinks.js:12:19:12:31 | req.query.foo | User-provided value |
311+
| 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 | $@ flows to here and is interpreted as a template, which may contain code. | template-sinks.js:17:19:17:31 | req.query.foo | User-provided value |
312+
| 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 | $@ flows to here and is interpreted as a template, which may contain code. | template-sinks.js:17:19:17:31 | req.query.foo | User-provided value |
313+
| 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 | $@ flows to here and is interpreted as a template, which may contain code. | template-sinks.js:17:19:17:31 | req.query.foo | User-provided value |
314+
| 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 | $@ flows to here and is interpreted as a template, which may contain code. | template-sinks.js:17:19:17:31 | req.query.foo | User-provided value |
315+
| 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 | $@ flows to here and is interpreted as a template, which may contain code. | template-sinks.js:17:19:17:31 | req.query.foo | User-provided value |
316+
| 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 | $@ flows to here and is interpreted as a template, which may contain code. | template-sinks.js:17:19:17:31 | req.query.foo | User-provided value |
317+
| 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 | $@ flows to here and is interpreted as a template, which may contain code. | template-sinks.js:17:19:17:31 | req.query.foo | User-provided value |
318+
| 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 | $@ flows to here and is interpreted as a template, which may contain code. | template-sinks.js:17:19:17:31 | req.query.foo | User-provided value |
319+
| 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 | $@ flows to here and is interpreted as a template, which may contain code. | template-sinks.js:17:19:17:31 | req.query.foo | User-provided value |
320+
| 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 | $@ flows to here and is interpreted as a template, which may contain code. | template-sinks.js:17:19:17:31 | req.query.foo | User-provided value |
321+
| 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 | $@ flows to here and is interpreted as a template, which may contain code. | template-sinks.js:17:19:17:31 | req.query.foo | User-provided value |
322+
| 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 | $@ flows to here and is interpreted as a template, which may contain code. | template-sinks.js:17:19:17:31 | req.query.foo | User-provided value |
323+
| 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 | $@ flows to here and is interpreted as a template, which may contain code. | template-sinks.js:17:19:17:31 | req.query.foo | User-provided value |
324+
| 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 | $@ flows to here and is interpreted as a template, which may contain code. | template-sinks.js:17:19:17:31 | req.query.foo | User-provided value |
295325
| 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) | $@ flows to here and is interpreted as code. | tst.js:2:6:2:27 | documen ... on.href | User-provided value |
296326
| 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 | $@ flows to here and is interpreted as code. | tst.js:5:12:5:33 | documen ... on.hash | User-provided value |
297327
| tst.js:14:10:14:74 | documen ... , "$1") | tst.js:14:10:14:33 | documen ... .search | tst.js:14:10:14:74 | documen ... , "$1") | $@ flows to here and is interpreted as code. | tst.js:14:10:14:33 | documen ... .search | User-provided value |

0 commit comments

Comments
 (0)