Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 09b9a57

Browse files
committed
JS: More efficient reasoning through pipe
1 parent b0636dd commit 09b9a57

1 file changed

Lines changed: 11 additions & 29 deletions

File tree

  • javascript/ql/src/semmle/javascript/security/dataflow

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

Lines changed: 11 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -34,30 +34,16 @@ module ZipSlip {
3434
}
3535

3636
/**
37-
* Holds if `node1` flows to `node2` in one step by virtue of
38-
* `node2` being of the form `.pipe(node1)`. The reason this flow
39-
* exists is that `.pipe` returns its argument to make chained
40-
* stream operations work.
37+
* Gets a node that can be a parsed zip archive.
4138
*/
42-
predicate pipeStep(DataFlow::Node node1, DataFlow::MethodCallNode node2) {
43-
node2.getMethodName() = "pipe" and
44-
node1 = node2.getArgument(0)
45-
}
46-
47-
/**
48-
* Holds if `node1` flows to `node2` in one step including the assumption that
49-
* `x` flows to `.pipe(x)`
50-
*/
51-
predicate stepsThroughPipe(DataFlow::Node node1, DataFlow::Node node2) {
52-
DataFlow::localFlowStep(node1, node2) or pipeStep(node1, node2)
53-
}
54-
55-
/**
56-
* Holds if `node1` flows to `node2` including the assumption that
57-
* `x` flows to `.pipe(x)`
58-
*/
59-
predicate flowsThroughPipe(DataFlow::Node node1, DataFlow::Node node2) {
60-
stepsThroughPipe*(node1, node2)
39+
DataFlow::SourceNode parsedArchive() {
40+
result = DataFlow::moduleImport("unzip").getAMemberCall("Parse")
41+
or
42+
// `streamProducer.pipe(unzip.Parse())` is a typical (but not
43+
// universal) pattern when using nodejs streams, whose return
44+
// value is the parsed stream.
45+
exists(DataFlow::MethodCallNode pipe | pipe.getMethodName() = "pipe"
46+
and parsedArchive().flowsTo(pipe.getArgument(0)))
6147
}
6248

6349
/**
@@ -77,11 +63,7 @@ module ZipSlip {
7763
*/
7864
class UnzipEntrySource extends Source {
7965
UnzipEntrySource() {
80-
exists(DataFlow::SourceNode parsed |
81-
flowsThroughPipe(DataFlow::moduleImport("unzip").getAMemberCall("Parse"), parsed)
82-
and
83-
this = parsed.getAMemberCall("on").getCallback(1).getParameter(0).getAPropertyRead("path")
84-
)
66+
this = parsedArchive().getAMemberCall("on").getCallback(1).getParameter(0).getAPropertyRead("path")
8567
}
8668
}
8769

@@ -107,7 +89,7 @@ module ZipSlip {
10789
* Gets a string which suffices to search for to ensure that a
10890
* filepath will not refer to parent directories.
10991
*/
110-
string getAParentDirName() { result = any(string s | s = ".." or s = "../") }
92+
string getAParentDirName() { result = ".." or result = "../" }
11193

11294
/** A check that a path string does not include '..' */
11395
class NoParentDirSanitizerGuard extends SanitizerGuard {

0 commit comments

Comments
 (0)