Skip to content

Commit 9c3fcb6

Browse files
author
Stephan Brandauer
committed
precise tracking of handlebars arguments
1 parent a28e9c5 commit 9c3fcb6

File tree

3 files changed

+185
-85
lines changed

3 files changed

+185
-85
lines changed

javascript/ql/lib/semmle/javascript/frameworks/Handlebars.qll

Lines changed: 73 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -29,23 +29,66 @@ module Handlebars {
2929
}
3030

3131
/** Provides logic for taint steps for the handlebars library. */
32-
module TaintStep {
32+
private module HandlebarsTaintSteps {
3333
/**
34-
* Gets a `SourceNode` tracked from a compilation of a Handlebars template.
34+
* Gets a reference to a compiled Handlebars template.
3535
*/
36-
private DataFlow::SourceNode compiledHandlebarsTemplate(DataFlow::Node originalCall) {
37-
result = compiledHandlebarsTemplate(DataFlow::TypeTracker::end(), originalCall)
36+
private DataFlow::SourceNode compiledTemplate(DataFlow::CallNode compileCall) {
37+
result = compiledTemplate(DataFlow::TypeTracker::end(), compileCall)
3838
}
3939

40-
private DataFlow::SourceNode compiledHandlebarsTemplate(
41-
DataFlow::TypeTracker t, DataFlow::Node originalCall
40+
private DataFlow::SourceNode compiledTemplate(
41+
DataFlow::TypeTracker t, DataFlow::CallNode compileCall
4242
) {
4343
t.start() and
4444
result = any(Handlebars::Handlebars hb).getAMethodCall(["compile", "template"]) and
45-
result = originalCall
45+
result = compileCall
4646
or
47-
exists(DataFlow::TypeTracker t2 |
48-
result = compiledHandlebarsTemplate(t2, originalCall).track(t2, t)
47+
exists(DataFlow::TypeTracker t2 | result = compiledTemplate(t2, compileCall).track(t2, t))
48+
}
49+
50+
private predicate isHelperParam(
51+
string helperName, DataFlow::FunctionNode helperFunction, DataFlow::ParameterNode param,
52+
int paramIndex
53+
) {
54+
exists(DataFlow::CallNode registerHelperCall |
55+
registerHelperCall = any(Handlebars::Handlebars hb).getAMethodCall("registerHelper") and
56+
registerHelperCall.getArgument(0).mayHaveStringValue(helperName) and
57+
helperFunction = registerHelperCall.getArgument(1).getAFunctionValue() and
58+
param = helperFunction.getParameter(paramIndex)
59+
)
60+
}
61+
62+
/** Holds if `call` is a block wrapped inside curly braces inside the template `templateText`. */
63+
bindingset[templateText]
64+
predicate templateHelperParamBlock(string templateText, string call) {
65+
call = templateText.regexpFind("\\{\\{[^}]+\\}\\}", _, _).regexpReplaceAll("[{}]", "").trim() and
66+
call.regexpMatch(".*\\s.*")
67+
}
68+
69+
/**
70+
* Holds for calls to helpers from handlebars templates.
71+
*
72+
* ```javascript
73+
* hb.compile("contents of file {{path}} are: {{catFile path}} {{echo p1 p2}}");
74+
* ```
75+
*
76+
* In the example, the predicate will hold for:
77+
*
78+
* * helperName="catFile", argIdx=1, arg="path"
79+
* * helperName="echo", argIdx=1, arg="p1"
80+
* * helperName="echo", argIdx=2, arg="p2"
81+
*
82+
* The initial `{{path}}` will not be considered, as it has no arguments.
83+
*/
84+
bindingset[templateText]
85+
private predicate isTemplateHelperCallArg(
86+
string templateText, string helperName, int argIdx, string argVal
87+
) {
88+
exists(string call | templateHelperParamBlock(templateText, call) |
89+
helperName = call.regexpFind("[^\\s]+", 0, _) and
90+
argIdx >= 0 and
91+
argVal = call.regexpFind("[^\\s]+", argIdx + 1, _)
4992
)
5093
}
5194

@@ -71,29 +114,26 @@ module TaintStep {
71114
* ```
72115
*/
73116
private predicate isHandlebarsArgStep(DataFlow::Node pred, DataFlow::Node succ) {
74-
exists(string helperName |
75-
exists(DataFlow::CallNode templatingCall, DataFlow::CallNode compileCall |
76-
templatingCall = compiledHandlebarsTemplate(compileCall).getACall() and
77-
pred = templatingCall.getAnArgument().getALocalSource().getAPropertyWrite().getRhs() and
78-
(
79-
compileCall
80-
.getArgument(0)
81-
.mayHaveStringValue(any(string templateText |
82-
// an approximation: if the template contains the
83-
// helper name, it's probably a helper call
84-
templateText.matches("%" + helperName + "%")
85-
))
86-
or
87-
// When we don't have a string value, we can't be sure
88-
// and will assume a step.
89-
not exists(string s | compileCall.getArgument(0).mayHaveStringValue(s))
117+
exists(
118+
string helperName, DataFlow::CallNode templatingCall, DataFlow::CallNode compileCall,
119+
DataFlow::FunctionNode helperFunction
120+
|
121+
templatingCall = compiledTemplate(compileCall).getACall() and
122+
(
123+
exists(string templateText, string paramName, int argIdx |
124+
compileCall.getArgument(0).mayHaveStringValue(templateText)
125+
|
126+
pred =
127+
templatingCall.getAnArgument().getALocalSource().getAPropertyWrite(paramName).getRhs() and
128+
isTemplateHelperCallArg(templateText, helperName, argIdx, paramName) and
129+
isHelperParam(helperName, helperFunction, succ, argIdx)
90130
)
91-
) and
92-
exists(DataFlow::CallNode registerHelperCall, DataFlow::FunctionNode helperFunc |
93-
registerHelperCall = any(Handlebars::Handlebars hb).getAMethodCall("registerHelper") and
94-
registerHelperCall.getArgument(0).mayHaveStringValue(helperName) and
95-
helperFunc = registerHelperCall.getArgument(1).getAFunctionValue() and
96-
helperFunc.getAParameter() = succ
131+
or
132+
// When we don't have a string value, we can't be sure
133+
// and will assume a step.
134+
not exists(string s | compileCall.getArgument(0).mayHaveStringValue(s)) and
135+
pred = templatingCall.getAnArgument().getALocalSource().getAPropertyWrite().getRhs() and
136+
isHelperParam(helperName, helperFunction, succ, _)
97137
)
98138
)
99139
}
@@ -105,8 +145,8 @@ module TaintStep {
105145
class HandlebarsStep extends DataFlow::SharedFlowStep {
106146
DataFlow::CallNode templatingCall;
107147

108-
override predicate step(DataFlow::Node node1, DataFlow::Node node2) {
109-
isHandlebarsArgStep(node1, node2)
148+
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
149+
isHandlebarsArgStep(pred, succ)
110150
}
111151
}
112152
}

javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected

Lines changed: 85 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1541,25 +1541,39 @@ nodes
15411541
| express.js:8:20:8:32 | req.query.bar |
15421542
| express.js:8:20:8:32 | req.query.bar |
15431543
| express.js:8:20:8:32 | req.query.bar |
1544-
| handlebars.js:19:46:19:60 | req.params.path |
1545-
| handlebars.js:19:46:19:60 | req.params.path |
1546-
| handlebars.js:19:46:19:60 | req.params.path |
1547-
| handlebars.js:19:46:19:60 | req.params.path |
1548-
| handlebars.js:19:46:19:60 | req.params.path |
1549-
| handlebars.js:22:18:22:25 | filePath |
1550-
| handlebars.js:22:18:22:25 | filePath |
1551-
| handlebars.js:22:18:22:25 | filePath |
1552-
| handlebars.js:22:18:22:25 | filePath |
1553-
| handlebars.js:23:28:23:35 | filePath |
1554-
| handlebars.js:23:28:23:35 | filePath |
1555-
| handlebars.js:23:28:23:35 | filePath |
1556-
| handlebars.js:23:28:23:35 | filePath |
1557-
| handlebars.js:23:28:23:35 | filePath |
1558-
| handlebars.js:31:43:31:57 | req.params.name |
1559-
| handlebars.js:31:43:31:57 | req.params.name |
1560-
| handlebars.js:31:43:31:57 | req.params.name |
1561-
| handlebars.js:31:43:31:57 | req.params.name |
1562-
| handlebars.js:31:43:31:57 | req.params.name |
1544+
| handlebars.js:10:51:10:58 | filePath |
1545+
| handlebars.js:10:51:10:58 | filePath |
1546+
| handlebars.js:10:51:10:58 | filePath |
1547+
| handlebars.js:10:51:10:58 | filePath |
1548+
| handlebars.js:11:32:11:39 | filePath |
1549+
| handlebars.js:11:32:11:39 | filePath |
1550+
| handlebars.js:11:32:11:39 | filePath |
1551+
| handlebars.js:11:32:11:39 | filePath |
1552+
| handlebars.js:11:32:11:39 | filePath |
1553+
| handlebars.js:13:73:13:80 | filePath |
1554+
| handlebars.js:13:73:13:80 | filePath |
1555+
| handlebars.js:13:73:13:80 | filePath |
1556+
| handlebars.js:13:73:13:80 | filePath |
1557+
| handlebars.js:15:25:15:32 | filePath |
1558+
| handlebars.js:15:25:15:32 | filePath |
1559+
| handlebars.js:15:25:15:32 | filePath |
1560+
| handlebars.js:15:25:15:32 | filePath |
1561+
| handlebars.js:15:25:15:32 | filePath |
1562+
| handlebars.js:29:46:29:60 | req.params.path |
1563+
| handlebars.js:29:46:29:60 | req.params.path |
1564+
| handlebars.js:29:46:29:60 | req.params.path |
1565+
| handlebars.js:29:46:29:60 | req.params.path |
1566+
| handlebars.js:29:46:29:60 | req.params.path |
1567+
| handlebars.js:37:43:37:57 | req.params.name |
1568+
| handlebars.js:37:43:37:57 | req.params.name |
1569+
| handlebars.js:37:43:37:57 | req.params.name |
1570+
| handlebars.js:37:43:37:57 | req.params.name |
1571+
| handlebars.js:37:43:37:57 | req.params.name |
1572+
| handlebars.js:43:15:43:29 | req.params.path |
1573+
| handlebars.js:43:15:43:29 | req.params.path |
1574+
| handlebars.js:43:15:43:29 | req.params.path |
1575+
| handlebars.js:43:15:43:29 | req.params.path |
1576+
| handlebars.js:43:15:43:29 | req.params.path |
15631577
| normalizedPaths.js:11:7:11:27 | path |
15641578
| normalizedPaths.js:11:7:11:27 | path |
15651579
| normalizedPaths.js:11:7:11:27 | path |
@@ -6433,30 +6447,54 @@ edges
64336447
| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) |
64346448
| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) |
64356449
| express.js:8:20:8:32 | req.query.bar | express.js:8:20:8:32 | req.query.bar |
6436-
| handlebars.js:19:46:19:60 | req.params.path | handlebars.js:22:18:22:25 | filePath |
6437-
| handlebars.js:19:46:19:60 | req.params.path | handlebars.js:22:18:22:25 | filePath |
6438-
| handlebars.js:19:46:19:60 | req.params.path | handlebars.js:22:18:22:25 | filePath |
6439-
| handlebars.js:19:46:19:60 | req.params.path | handlebars.js:22:18:22:25 | filePath |
6440-
| handlebars.js:19:46:19:60 | req.params.path | handlebars.js:22:18:22:25 | filePath |
6441-
| handlebars.js:19:46:19:60 | req.params.path | handlebars.js:22:18:22:25 | filePath |
6442-
| handlebars.js:19:46:19:60 | req.params.path | handlebars.js:22:18:22:25 | filePath |
6443-
| handlebars.js:19:46:19:60 | req.params.path | handlebars.js:22:18:22:25 | filePath |
6444-
| handlebars.js:22:18:22:25 | filePath | handlebars.js:23:28:23:35 | filePath |
6445-
| handlebars.js:22:18:22:25 | filePath | handlebars.js:23:28:23:35 | filePath |
6446-
| handlebars.js:22:18:22:25 | filePath | handlebars.js:23:28:23:35 | filePath |
6447-
| handlebars.js:22:18:22:25 | filePath | handlebars.js:23:28:23:35 | filePath |
6448-
| handlebars.js:22:18:22:25 | filePath | handlebars.js:23:28:23:35 | filePath |
6449-
| handlebars.js:22:18:22:25 | filePath | handlebars.js:23:28:23:35 | filePath |
6450-
| handlebars.js:22:18:22:25 | filePath | handlebars.js:23:28:23:35 | filePath |
6451-
| handlebars.js:22:18:22:25 | filePath | handlebars.js:23:28:23:35 | filePath |
6452-
| handlebars.js:31:43:31:57 | req.params.name | handlebars.js:22:18:22:25 | filePath |
6453-
| handlebars.js:31:43:31:57 | req.params.name | handlebars.js:22:18:22:25 | filePath |
6454-
| handlebars.js:31:43:31:57 | req.params.name | handlebars.js:22:18:22:25 | filePath |
6455-
| handlebars.js:31:43:31:57 | req.params.name | handlebars.js:22:18:22:25 | filePath |
6456-
| handlebars.js:31:43:31:57 | req.params.name | handlebars.js:22:18:22:25 | filePath |
6457-
| handlebars.js:31:43:31:57 | req.params.name | handlebars.js:22:18:22:25 | filePath |
6458-
| handlebars.js:31:43:31:57 | req.params.name | handlebars.js:22:18:22:25 | filePath |
6459-
| handlebars.js:31:43:31:57 | req.params.name | handlebars.js:22:18:22:25 | filePath |
6450+
| handlebars.js:10:51:10:58 | filePath | handlebars.js:11:32:11:39 | filePath |
6451+
| handlebars.js:10:51:10:58 | filePath | handlebars.js:11:32:11:39 | filePath |
6452+
| handlebars.js:10:51:10:58 | filePath | handlebars.js:11:32:11:39 | filePath |
6453+
| handlebars.js:10:51:10:58 | filePath | handlebars.js:11:32:11:39 | filePath |
6454+
| handlebars.js:10:51:10:58 | filePath | handlebars.js:11:32:11:39 | filePath |
6455+
| handlebars.js:10:51:10:58 | filePath | handlebars.js:11:32:11:39 | filePath |
6456+
| handlebars.js:10:51:10:58 | filePath | handlebars.js:11:32:11:39 | filePath |
6457+
| handlebars.js:10:51:10:58 | filePath | handlebars.js:11:32:11:39 | filePath |
6458+
| handlebars.js:13:73:13:80 | filePath | handlebars.js:15:25:15:32 | filePath |
6459+
| handlebars.js:13:73:13:80 | filePath | handlebars.js:15:25:15:32 | filePath |
6460+
| handlebars.js:13:73:13:80 | filePath | handlebars.js:15:25:15:32 | filePath |
6461+
| handlebars.js:13:73:13:80 | filePath | handlebars.js:15:25:15:32 | filePath |
6462+
| handlebars.js:13:73:13:80 | filePath | handlebars.js:15:25:15:32 | filePath |
6463+
| handlebars.js:13:73:13:80 | filePath | handlebars.js:15:25:15:32 | filePath |
6464+
| handlebars.js:13:73:13:80 | filePath | handlebars.js:15:25:15:32 | filePath |
6465+
| handlebars.js:13:73:13:80 | filePath | handlebars.js:15:25:15:32 | filePath |
6466+
| handlebars.js:29:46:29:60 | req.params.path | handlebars.js:10:51:10:58 | filePath |
6467+
| handlebars.js:29:46:29:60 | req.params.path | handlebars.js:10:51:10:58 | filePath |
6468+
| handlebars.js:29:46:29:60 | req.params.path | handlebars.js:10:51:10:58 | filePath |
6469+
| handlebars.js:29:46:29:60 | req.params.path | handlebars.js:10:51:10:58 | filePath |
6470+
| handlebars.js:29:46:29:60 | req.params.path | handlebars.js:10:51:10:58 | filePath |
6471+
| handlebars.js:29:46:29:60 | req.params.path | handlebars.js:10:51:10:58 | filePath |
6472+
| handlebars.js:29:46:29:60 | req.params.path | handlebars.js:10:51:10:58 | filePath |
6473+
| handlebars.js:29:46:29:60 | req.params.path | handlebars.js:10:51:10:58 | filePath |
6474+
| handlebars.js:37:43:37:57 | req.params.name | handlebars.js:10:51:10:58 | filePath |
6475+
| handlebars.js:37:43:37:57 | req.params.name | handlebars.js:10:51:10:58 | filePath |
6476+
| handlebars.js:37:43:37:57 | req.params.name | handlebars.js:10:51:10:58 | filePath |
6477+
| handlebars.js:37:43:37:57 | req.params.name | handlebars.js:10:51:10:58 | filePath |
6478+
| handlebars.js:37:43:37:57 | req.params.name | handlebars.js:10:51:10:58 | filePath |
6479+
| handlebars.js:37:43:37:57 | req.params.name | handlebars.js:10:51:10:58 | filePath |
6480+
| handlebars.js:37:43:37:57 | req.params.name | handlebars.js:10:51:10:58 | filePath |
6481+
| handlebars.js:37:43:37:57 | req.params.name | handlebars.js:10:51:10:58 | filePath |
6482+
| handlebars.js:37:43:37:57 | req.params.name | handlebars.js:13:73:13:80 | filePath |
6483+
| handlebars.js:37:43:37:57 | req.params.name | handlebars.js:13:73:13:80 | filePath |
6484+
| handlebars.js:37:43:37:57 | req.params.name | handlebars.js:13:73:13:80 | filePath |
6485+
| handlebars.js:37:43:37:57 | req.params.name | handlebars.js:13:73:13:80 | filePath |
6486+
| handlebars.js:37:43:37:57 | req.params.name | handlebars.js:13:73:13:80 | filePath |
6487+
| handlebars.js:37:43:37:57 | req.params.name | handlebars.js:13:73:13:80 | filePath |
6488+
| handlebars.js:37:43:37:57 | req.params.name | handlebars.js:13:73:13:80 | filePath |
6489+
| handlebars.js:37:43:37:57 | req.params.name | handlebars.js:13:73:13:80 | filePath |
6490+
| handlebars.js:43:15:43:29 | req.params.path | handlebars.js:13:73:13:80 | filePath |
6491+
| handlebars.js:43:15:43:29 | req.params.path | handlebars.js:13:73:13:80 | filePath |
6492+
| handlebars.js:43:15:43:29 | req.params.path | handlebars.js:13:73:13:80 | filePath |
6493+
| handlebars.js:43:15:43:29 | req.params.path | handlebars.js:13:73:13:80 | filePath |
6494+
| handlebars.js:43:15:43:29 | req.params.path | handlebars.js:13:73:13:80 | filePath |
6495+
| handlebars.js:43:15:43:29 | req.params.path | handlebars.js:13:73:13:80 | filePath |
6496+
| handlebars.js:43:15:43:29 | req.params.path | handlebars.js:13:73:13:80 | filePath |
6497+
| handlebars.js:43:15:43:29 | req.params.path | handlebars.js:13:73:13:80 | filePath |
64606498
| normalizedPaths.js:11:7:11:27 | path | normalizedPaths.js:13:19:13:22 | path |
64616499
| normalizedPaths.js:11:7:11:27 | path | normalizedPaths.js:13:19:13:22 | path |
64626500
| normalizedPaths.js:11:7:11:27 | path | normalizedPaths.js:13:19:13:22 | path |
@@ -9887,8 +9925,10 @@ edges
98879925
| TaintedPath.js:213:45:213:48 | path | TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:213:45:213:48 | path | This path depends on $@. | TaintedPath.js:211:24:211:30 | req.url | a user-provided value |
98889926
| TaintedPath.js:214:35:214:38 | path | TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:214:35:214:38 | path | This path depends on $@. | TaintedPath.js:211:24:211:30 | req.url | a user-provided value |
98899927
| express.js:8:20:8:32 | req.query.bar | express.js:8:20:8:32 | req.query.bar | express.js:8:20:8:32 | req.query.bar | This path depends on $@. | express.js:8:20:8:32 | req.query.bar | a user-provided value |
9890-
| handlebars.js:23:28:23:35 | filePath | handlebars.js:19:46:19:60 | req.params.path | handlebars.js:23:28:23:35 | filePath | This path depends on $@. | handlebars.js:19:46:19:60 | req.params.path | a user-provided value |
9891-
| handlebars.js:23:28:23:35 | filePath | handlebars.js:31:43:31:57 | req.params.name | handlebars.js:23:28:23:35 | filePath | This path depends on $@. | handlebars.js:31:43:31:57 | req.params.name | a user-provided value |
9928+
| handlebars.js:11:32:11:39 | filePath | handlebars.js:29:46:29:60 | req.params.path | handlebars.js:11:32:11:39 | filePath | This path depends on $@. | handlebars.js:29:46:29:60 | req.params.path | a user-provided value |
9929+
| handlebars.js:11:32:11:39 | filePath | handlebars.js:37:43:37:57 | req.params.name | handlebars.js:11:32:11:39 | filePath | This path depends on $@. | handlebars.js:37:43:37:57 | req.params.name | a user-provided value |
9930+
| handlebars.js:15:25:15:32 | filePath | handlebars.js:37:43:37:57 | req.params.name | handlebars.js:15:25:15:32 | filePath | This path depends on $@. | handlebars.js:37:43:37:57 | req.params.name | a user-provided value |
9931+
| handlebars.js:15:25:15:32 | filePath | handlebars.js:43:15:43:29 | req.params.path | handlebars.js:15:25:15:32 | filePath | This path depends on $@. | handlebars.js:43:15:43:29 | req.params.path | a user-provided value |
98929932
| normalizedPaths.js:13:19:13:22 | path | normalizedPaths.js:11:14:11:27 | req.query.path | normalizedPaths.js:13:19:13:22 | path | This path depends on $@. | normalizedPaths.js:11:14:11:27 | req.query.path | a user-provided value |
98939933
| normalizedPaths.js:14:19:14:29 | './' + path | normalizedPaths.js:11:14:11:27 | req.query.path | normalizedPaths.js:14:19:14:29 | './' + path | This path depends on $@. | normalizedPaths.js:11:14:11:27 | req.query.path | a user-provided value |
98949934
| normalizedPaths.js:15:19:15:38 | path + '/index.html' | normalizedPaths.js:11:14:11:27 | req.query.path | normalizedPaths.js:15:19:15:38 | path + '/index.html' | This path depends on $@. | normalizedPaths.js:11:14:11:27 | req.query.path | a user-provided value |

javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/handlebars.js

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,20 @@ const app = express();
77
const data = {};
88

99
function init() {
10-
hb.registerHelper("catFile", catFile);
10+
hb.registerHelper("catFile", function catFile(filePath) {
11+
return fs.readFileSync(filePath); // SINK (reads file)
12+
});
13+
hb.registerHelper("prependToLines", function prependToLines(prefix, filePath) {
14+
return fs
15+
.readFileSync(filePath)
16+
.split("\n")
17+
.map((line) => prefix + line)
18+
.join("\n");
19+
});
1120
data.compiledFileAccess = hb.compile("contents of file {{path}} are: {{catFile path}}")
1221
data.compiledBenign = hb.compile("hello, {{name}}");
1322
data.compiledUnknown = hb.compile(fs.readFileSync("greeting.template"));
23+
data.compiledMixed = hb.compile("helpers may have several args, like here: {{prependToLines prefix path}}");
1424
}
1525

1626
init();
@@ -19,14 +29,24 @@ app.get('/some/path1', function (req, res) {
1929
res.send(data.compiledFileAccess({ path: req.params.path })); // NOT ALLOWED (template uses vulnerable catFile)
2030
});
2131

22-
function catFile(filePath) {
23-
return fs.readFileSync(filePath); // SINK (reads file)
24-
}
25-
2632
app.get('/some/path2', function (req, res) {
2733
res.send(data.compiledBenign({ name: req.params.name })); // ALLOWED (this template does not use catFile)
2834
});
2935

30-
app.get('/some/path3', function (req, res) {
31-
res.send(data.compiledUnknown({ name: req.params.name })); // NOT ALLOWED (could be using vulnerable catFile)
36+
app.get('/some/path3', function (req, res) {
37+
res.send(data.compiledUnknown({ name: req.params.name })); // NOT ALLOWED (could be using a vulnerable helper)
38+
});
39+
40+
app.get('/some/path4', function (req, res) {
41+
res.send(data.compiledMixed({
42+
prefix: ">>> ",
43+
path: req.params.path // NOT ALLOWED (template uses vulnerable helper)
44+
}));
45+
});
46+
47+
app.get('/some/path5', function (req, res) {
48+
res.send(data.compiledMixed({
49+
prefix: req.params.prefix, // ALLOWED (this parameter is safe)
50+
path: "data/path-5.txt"
51+
}));
3252
});

0 commit comments

Comments
 (0)