mirror of
https://github.com/github/codeql.git
synced 2026-05-01 03:35:13 +02:00
JS: extract PrintfStyleCall out of TaintedFormatString
This commit is contained in:
@@ -66,6 +66,7 @@ import semmle.javascript.frameworks.React
|
||||
import semmle.javascript.frameworks.ReactNative
|
||||
import semmle.javascript.frameworks.Request
|
||||
import semmle.javascript.frameworks.SQL
|
||||
import semmle.javascript.frameworks.StringFormatters
|
||||
import semmle.javascript.frameworks.UriLibraries
|
||||
import semmle.javascript.frameworks.XmlParsers
|
||||
import semmle.javascript.frameworks.xUnit
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* Provides classes for modeling string formatting libraries.
|
||||
*/
|
||||
|
||||
import javascript
|
||||
|
||||
/**
|
||||
* A printf-style call that substitutes the embedded format specifiers of a format string for the format arguments.
|
||||
*/
|
||||
abstract class PrintfStyleCall extends DataFlow::CallNode {
|
||||
/**
|
||||
* Gets the format string.
|
||||
*/
|
||||
abstract DataFlow::Node getFormatString();
|
||||
|
||||
/**
|
||||
* Gets the ith argument to the format string.
|
||||
*/
|
||||
abstract DataFlow::Node getFormatArgument(int i);
|
||||
}
|
||||
|
||||
private class LibraryFormatter extends PrintfStyleCall {
|
||||
|
||||
int formatIndex;
|
||||
|
||||
LibraryFormatter() {
|
||||
// built-in Node.js functions
|
||||
exists (string mod, string meth |
|
||||
mod = "console" and (
|
||||
(
|
||||
meth = "debug" or
|
||||
meth = "error" or
|
||||
meth = "info" or
|
||||
meth = "log" or
|
||||
meth = "trace" or
|
||||
meth = "warn"
|
||||
) and
|
||||
formatIndex = 0
|
||||
or
|
||||
meth = "assert" and formatIndex = 1
|
||||
)
|
||||
or
|
||||
mod = "util" and (
|
||||
(meth = "format" or meth = "log") and formatIndex = 0
|
||||
or
|
||||
meth = "formatWithOptions" and formatIndex = 1
|
||||
)
|
||||
|
|
||||
// `console` and `util` are available both as modules...
|
||||
this = DataFlow::moduleMember(mod, meth).getACall()
|
||||
or
|
||||
// ...and as globals
|
||||
this = DataFlow::globalVarRef(mod).getAMemberCall(meth)
|
||||
)
|
||||
or
|
||||
(
|
||||
// https://www.npmjs.com/package/printf
|
||||
this = DataFlow::moduleImport("printf").getACall() and
|
||||
formatIndex in [0..1]
|
||||
or
|
||||
// https://www.npmjs.com/package/printj
|
||||
exists (string fn | fn = "sprintf" or fn = "vsprintf" |
|
||||
this = DataFlow::moduleMember("printj", fn).getACall() and
|
||||
formatIndex = 0
|
||||
)
|
||||
or
|
||||
// https://www.npmjs.com/package/format-util
|
||||
this = DataFlow::moduleImport("format-util").getACall() and
|
||||
formatIndex = 0
|
||||
or
|
||||
// https://www.npmjs.com/package/string-template
|
||||
this = DataFlow::moduleImport("string-template").getACall() and
|
||||
formatIndex = 0
|
||||
or
|
||||
this = DataFlow::moduleImport("string-template/compile").getACall() and
|
||||
formatIndex = 0
|
||||
or
|
||||
// https://www.npmjs.com/package/sprintf-js
|
||||
exists (string meth | meth = "sprintf" or meth = "vsprintf" |
|
||||
this = DataFlow::moduleMember("sprintf-js", meth).getACall() and
|
||||
formatIndex = 0
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getFormatString() {
|
||||
result = getArgument(formatIndex)
|
||||
}
|
||||
|
||||
override DataFlow::Node getFormatArgument(int i) {
|
||||
i >= 0 and
|
||||
result = getArgument(formatIndex + 1 + i)
|
||||
}
|
||||
}
|
||||
@@ -58,57 +58,10 @@ module TaintedFormatString {
|
||||
*/
|
||||
class FormatSink extends Sink {
|
||||
FormatSink() {
|
||||
exists (DataFlow::CallNode call, int argIdx |
|
||||
// built-in Node.js functions
|
||||
exists (string mod, string meth |
|
||||
mod = "console" and
|
||||
(meth = "debug" or meth = "error" or meth = "info" or
|
||||
meth = "log" or meth = "trace" or meth = "warn") and
|
||||
argIdx = 0
|
||||
or
|
||||
mod = "console" and meth = "assert" and argIdx = 1
|
||||
or
|
||||
mod = "util" and (meth = "format" or meth = "log") and argIdx = 0
|
||||
or
|
||||
mod = "util" and meth = "formatWithOptions" and argIdx = 1
|
||||
|
|
||||
// `console` and `util` are available both as modules...
|
||||
call = DataFlow::moduleMember(mod, meth).getACall()
|
||||
or
|
||||
// ...and as globals
|
||||
call = DataFlow::globalVarRef(mod).getAMemberCall(meth)
|
||||
)
|
||||
or
|
||||
// https://www.npmjs.com/package/printf
|
||||
call = DataFlow::moduleImport("printf").getACall() and
|
||||
argIdx in [0..1]
|
||||
or
|
||||
// https://www.npmjs.com/package/printj
|
||||
exists (string fn | fn = "sprintf" or fn = "vsprintf" |
|
||||
call = DataFlow::moduleMember("printj", fn).getACall() and
|
||||
argIdx = 0
|
||||
)
|
||||
or
|
||||
// https://www.npmjs.com/package/format-util
|
||||
call = DataFlow::moduleImport("format-util").getACall() and
|
||||
argIdx = 0
|
||||
or
|
||||
// https://www.npmjs.com/package/string-template
|
||||
call = DataFlow::moduleImport("string-template").getACall() and
|
||||
argIdx = 0
|
||||
or
|
||||
call = DataFlow::moduleImport("string-template/compile").getACall() and
|
||||
argIdx = 0
|
||||
or
|
||||
// https://www.npmjs.com/package/sprintf-js
|
||||
exists (string meth | meth = "sprintf" or meth = "vsprintf" |
|
||||
call = DataFlow::moduleMember("sprintf-js", meth).getACall() and
|
||||
argIdx = 0
|
||||
)
|
||||
|
|
||||
this = call.getArgument(argIdx) and
|
||||
exists(PrintfStyleCall printf |
|
||||
this = printf.getFormatString() and
|
||||
// exclude trivial case where there are no arguments to interpolate
|
||||
exists(call.getArgument(argIdx+1))
|
||||
exists(printf.getFormatArgument(_))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user