Skip to content

Commit c83c27c

Browse files
committed
add extra sanity-check that the output looks good
1 parent 8d26f32 commit c83c27c

File tree

1 file changed

+14
-4
lines changed

1 file changed

+14
-4
lines changed

javascript/ql/src/semmle/javascript/security/UselessUseOfCat.qll

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,14 @@ private class CommandCall extends DataFlow::InvokeNode {
7474
}
7575
}
7676

77+
/**
78+
* Holds if the input `str` contains some character that might be interpreted in a non-trivial way by a shell.
79+
*/
80+
bindingset[str]
81+
predicate containsNonTrivialBashChar(string str) {
82+
exists(str.regexpFind("\\*|\\||>|<| |\\$|&|,|\\`| ", _, _))
83+
}
84+
7785
/**
7886
* Gets the constant string parts from a data-flow node.
7987
* Either the result is a constant string value that the node can hold, or the node is a string-concatenation and the result is the string parts from the concatenation.
@@ -97,7 +105,7 @@ class UselessCat extends CommandCall {
97105
getArgument(0).mayHaveStringValue(getACatExecuteable())
98106
) and
99107
// wildcards, pipes, redirections, other bash features, and multiple files (spaces) are OK.
100-
not exists(getNonCommandConstantString().regexpFind("\\*|\\||>|<| |\\$|&|,|\\`| ", _, _)) and
108+
not containsNonTrivialBashChar(getNonCommandConstantString()) and
101109
// Only acceptable option is "encoding", everything else is non-trivial to emulate with fs.readFile.
102110
(
103111
not exists(getOptionsArg())
@@ -146,7 +154,7 @@ module PrettyPrintCatCall {
146154
* Create a string representation of an equivalent call to `fs.readFile` for a given command execution `cat`.
147155
*/
148156
string createReadFileCall(UselessCat cat) {
149-
exists(string sync, string extraArg, string callback |
157+
exists(string sync, string extraArg, string callback, string fileArg |
150158
(if cat.isSync() then sync = "Sync" else sync = "") and
151159
(
152160
exists(cat.getOptionsArg()) and
@@ -163,10 +171,12 @@ module PrettyPrintCatCall {
163171
callback = createCallbackString(cat.getCallback())
164172
or
165173
callback = "" and not exists(cat.getCallback())
166-
)
174+
) and
175+
fileArg = createFileArgument(cat).trim() and
176+
not(containsNonTrivialBashChar(fileArg.regexpReplaceAll("\\$|\\`| ", ""))) // string concat might contain " ", template strings might contain "$" or `, and that is OK.
167177
|
168178
result =
169-
"fs.readFile" + sync + "(" + createFileArgument(cat).trim() + extraArg + callback + ")"
179+
"fs.readFile" + sync + "(" + fileArg + extraArg + callback + ")"
170180
)
171181
}
172182

0 commit comments

Comments
 (0)