Skip to content

Commit c5d3903

Browse files
authored
Merge pull request #2962 from erik-krogh/YetAnotherSanitizer
Approved by asgerf
2 parents bbcf0b5 + f03c672 commit c5d3903

File tree

4 files changed

+456
-6
lines changed

4 files changed

+456
-6
lines changed

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,15 @@ module TaintedPath {
197197
srclabel = dstlabel
198198
)
199199
or
200+
// foo.replace(/\./, "") and similar
201+
exists(DotRemovingReplaceCall call |
202+
src = call.getInput() and
203+
dst = call.getOutput() and
204+
srclabel.isAbsolute() and
205+
dstlabel.isAbsolute() and
206+
dstlabel.isNormalized()
207+
)
208+
or
200209
// path.join()
201210
exists(DataFlow::CallNode join, int n |
202211
join = NodeJSLib::Path::moduleMember("join").getACall()

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

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -213,17 +213,51 @@ module TaintedPath {
213213
output = this
214214
)
215215
or
216-
// non-global replace or replace of something other than /\.\./g
216+
// non-global replace or replace of something other than /\.\./g, /[/]/g, or /[\.]/g.
217217
this.getCalleeName() = "replace" and
218218
input = getReceiver() and
219219
output = this and
220-
not exists(RegExpLiteral literal, RegExpSequence seq |
220+
not exists(RegExpLiteral literal, RegExpTerm term |
221221
getArgument(0).getALocalSource().asExpr() = literal and
222222
literal.isGlobal() and
223-
literal.getRoot() = seq and
224-
seq.getChild(0).(RegExpConstant).getValue() = "." and
225-
seq.getChild(1).(RegExpConstant).getValue() = "." and
226-
seq.getNumChild() = 2
223+
literal.getRoot() = term
224+
|
225+
term.getAMatchedString() = "/" or
226+
term.getAMatchedString() = "." or
227+
term.getAMatchedString() = ".."
228+
)
229+
}
230+
231+
/**
232+
* Gets the input path to be normalized.
233+
*/
234+
DataFlow::Node getInput() { result = input }
235+
236+
/**
237+
* Gets the normalized path.
238+
*/
239+
DataFlow::Node getOutput() { result = output }
240+
}
241+
242+
/**
243+
* A call that removes all "." or ".." from a path, without also removing all forward slashes.
244+
*/
245+
class DotRemovingReplaceCall extends DataFlow::CallNode {
246+
DataFlow::Node input;
247+
DataFlow::Node output;
248+
249+
DotRemovingReplaceCall() {
250+
this.getCalleeName() = "replace" and
251+
input = getReceiver() and
252+
output = this and
253+
exists(RegExpLiteral literal, RegExpTerm term |
254+
getArgument(0).getALocalSource().asExpr() = literal and
255+
literal.isGlobal() and
256+
literal.getRoot() = term and
257+
not term.getAMatchedString() = "/"
258+
|
259+
term.getAMatchedString() = "." or
260+
term.getAMatchedString() = ".."
227261
)
228262
}
229263

0 commit comments

Comments
 (0)