Skip to content

Commit 14bada4

Browse files
committed
JS: Model consolidate and factor in template syntax from call site
1 parent 425bd7a commit 14bada4

6 files changed

Lines changed: 103 additions & 0 deletions

File tree

javascript/ql/src/semmle/javascript/frameworks/Templating.qll

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,15 @@ module Templating {
190190
TemplateFile getTemplateFile() {
191191
result = getTemplateFileNode().(TemplateFileReference).getTemplateFile()
192192
}
193+
194+
/**
195+
* Gets the template syntax used by this template instantiation, if known.
196+
*
197+
* If not known, the relevant syntax will be determined by a heuristic.
198+
*/
199+
TemplateSyntax getTemplateSyntax() {
200+
result = range.getTemplateSyntax()
201+
}
193202
}
194203

195204
/** Companion module to the `TemplateInstantiation` class. */
@@ -206,6 +215,13 @@ module Templating {
206215

207216
/** Gets a data flow node that refers to an object whose properties become variables in the template. */
208217
abstract DataFlow::Node getTemplateParamsNode();
218+
219+
/**
220+
* Gets the template syntax used by this template instantiation, if known.
221+
*
222+
* If not known, the relevant syntax will be determined by a heuristic.
223+
*/
224+
TemplateSyntax getTemplateSyntax() { none() }
209225
}
210226
}
211227

@@ -558,12 +574,20 @@ module Templating {
558574
result = getTemplateSyntaxInFolder(f.getParentContainer())
559575
}
560576

577+
private TemplateSyntax getTemplateSyntaxFromInstantiation(TemplateFile file) {
578+
result = any(TemplateInstantiaton inst | inst.getTemplateFile() = file).getTemplateSyntax()
579+
}
580+
561581
/**
562582
* Gets a template syntax likely to be used in the given file.
563583
*/
564584
TemplateSyntax getLikelyTemplateSyntax(TemplateFile file) {
585+
result = getTemplateSyntaxFromInstantiation(file)
586+
or
587+
not exists(getTemplateSyntaxFromInstantiation(file)) and
565588
result.getAFileExtension() = file.getExtension()
566589
or
590+
not exists(getTemplateSyntaxFromInstantiation(file)) and
567591
not file.getExtension() = any(TemplateSyntax s).getAFileExtension() and
568592
result = getTemplateSyntaxInFolder(file.getParentContainer())
569593
}
@@ -656,4 +680,38 @@ module Templating {
656680
result = tag.getFile().getParentContainer()
657681
}
658682
}
683+
684+
/**
685+
* A call to a member of the `consolidate` library, seen as a template instantiation.
686+
*/
687+
private class ConsolidateCall extends TemplateInstantiaton::Range, API::CallNode {
688+
string engine;
689+
690+
ConsolidateCall() {
691+
this = API::moduleImport("consolidate").getMember(engine).getACall()
692+
}
693+
694+
override TemplateSyntax getTemplateSyntax() {
695+
result.getAPackageName() = engine
696+
}
697+
698+
override DataFlow::SourceNode getOutput() {
699+
result = getParameter([1, 2]).getParameter(1).getAnImmediateUse()
700+
or
701+
not exists(getParameter([1, 2]).getParameter(1)) and
702+
result = this
703+
}
704+
705+
override DataFlow::Node getTemplateFileNode() {
706+
result = getArgument(0)
707+
}
708+
709+
override DataFlow::Node getTemplateContentNode() {
710+
none()
711+
}
712+
713+
override DataFlow::Node getTemplateParamsNode() {
714+
result = getArgument(1)
715+
}
716+
}
659717
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import * as consolidate from 'consolidate';
2+
3+
consolidate.ejs('views/instantiated_as_ejs.html', { data: 123 }, (err, html) => {});
4+
consolidate.handlebars('views/instantiated_as_hbs.html', { data: 123 }, (err, html) => {});
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
getTemplateInstantiationSyntax
2+
| consolidate.js:3:1:3:83 | consoli ... => {}) | ejs |
3+
| consolidate.js:4:1:4:90 | consoli ... => {}) | mustache |
4+
getLikelyTemplateSyntax
5+
| views/instantiated_as_ejs.html:0:0:0:0 | views/instantiated_as_ejs.html | ejs |
6+
| views/instantiated_as_hbs.html:0:0:0:0 | views/instantiated_as_hbs.html | mustache |
7+
xssSink
8+
| views/instantiated_as_ejs.html:4:9:4:23 | <%- xss_sink %> |
9+
| views/instantiated_as_hbs.html:7:9:7:24 | {{{ xss_sink }}} |
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import javascript
2+
import semmle.javascript.security.dataflow.Xss
3+
4+
query Templating::TemplateSyntax getTemplateInstantiationSyntax(Templating::TemplateInstantiaton inst) {
5+
result = inst.getTemplateSyntax()
6+
}
7+
8+
query Templating::TemplateSyntax getLikelyTemplateSyntax(Templating::TemplateFile file) {
9+
result = Templating::getLikelyTemplateSyntax(file)
10+
}
11+
12+
query DomBasedXss::Sink xssSink() {
13+
any()
14+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<html>
2+
<body>
3+
<%= safe %>
4+
<%- xss_sink %>
5+
6+
{{ safe }}
7+
{{{ safe }}}
8+
</body>
9+
</html>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<html>
2+
<body>
3+
<%= safe %>
4+
<%- safe %>
5+
6+
{{ safe }}
7+
{{{ xss_sink }}}
8+
</body>
9+
</html>

0 commit comments

Comments
 (0)