Skip to content

Commit f9b5846

Browse files
committed
add detection of sources directly used with blocks
1 parent 4ab6a7b commit f9b5846

File tree

1 file changed

+33
-22
lines changed

1 file changed

+33
-22
lines changed

ruby/ql/lib/codeql/ruby/security/ZipSlipCustomizations.qll

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,11 @@ module ZipSlip {
4545
*/
4646
private class GzipReaderOpen extends Source {
4747
GzipReaderOpen() {
48-
this = API::getTopLevelMember("Zlib").getMember("GzipReader").getReturn("open").asSource() and
48+
(
49+
this = API::getTopLevelMember("Zlib").getMember("GzipReader").getReturn("open").asSource()
50+
or
51+
this = API::getTopLevelMember("Zlib").getMember("GzipReader").getInstance().asSource()
52+
) and
4953
// If argument refers to a string object, then it's a hardcoded path and
5054
// this file is safe.
5155
not this.(DataFlow::CallNode)
@@ -61,19 +65,17 @@ module ZipSlip {
6165
*/
6266
private class TarReaderInstance extends Source {
6367
TarReaderInstance() {
64-
this =
65-
API::getTopLevelMember("Gem")
66-
.getMember("Package")
67-
.getMember("TarReader")
68-
.getInstance()
69-
.asSource() and
70-
// If argument refers to a string object, then it's a hardcoded path and
71-
// this file is safe.
72-
not this.(DataFlow::CallNode)
73-
.getArgument(0)
74-
.getALocalSource()
75-
.getConstantValue()
76-
.isStringlikeValue(_)
68+
exists(API::MethodAccessNode newTarReader |
69+
newTarReader =
70+
API::getTopLevelMember("Gem").getMember("Package").getMember("TarReader").getMethod("new")
71+
|
72+
// Unlike in two other modules, there's no check for the constant path because TarReader class is called with an `io` object and not filepath.
73+
// This, of course, can be modeled but probably in the internal IO.qll file
74+
// For now, I'm leaving this prone to false-positives
75+
not exists(newTarReader.getBlock()) and this = newTarReader.getReturn().asSource()
76+
or
77+
this = newTarReader.getBlock().getParameter(0).asSource()
78+
)
7779
}
7880
}
7981

@@ -82,14 +84,23 @@ module ZipSlip {
8284
*/
8385
private class ZipFileOpen extends Source {
8486
ZipFileOpen() {
85-
this = API::getTopLevelMember("Zip").getMember("File").getReturn("open").asSource() and
86-
// If argument refers to a string object, then it's a hardcoded path and
87-
// this file is safe.
88-
not this.(DataFlow::CallNode)
89-
.getArgument(0)
90-
.getALocalSource()
91-
.getConstantValue()
92-
.isStringlikeValue(_)
87+
exists(API::MethodAccessNode zipOpen |
88+
zipOpen = API::getTopLevelMember("Zip").getMember("File").getMethod("open") and
89+
// If argument refers to a string object, then it's a hardcoded path and
90+
// this file is safe.
91+
not zipOpen
92+
.getCallNode()
93+
.getArgument(0)
94+
.getALocalSource()
95+
.getConstantValue()
96+
.isStringlikeValue(_)
97+
|
98+
// the case with variable assignment `zip_file = Zip::File.open(path)`
99+
not exists(zipOpen.getBlock()) and this = zipOpen.getReturn().asSource()
100+
or
101+
// the case with direct block`Zip::File.open(path) do |zip_file|` case
102+
this = zipOpen.getBlock().getParameter(0).asSource()
103+
)
93104
}
94105
}
95106

0 commit comments

Comments
 (0)