mirror of
https://github.com/github/codeql.git
synced 2026-04-27 01:35:13 +02:00
@@ -30,5 +30,9 @@ module IndirectCommandInjection {
|
||||
override predicate isSink(DataFlow::Node sink) { isSinkWithHighlight(sink, _) }
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
|
||||
|
||||
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
argsParseStep(pred, succ)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,14 +47,70 @@ module IndirectCommandInjection {
|
||||
// `require('get-them-args')(...)` => `{ unknown: [], a: ... b: ... }`
|
||||
this = DataFlow::moduleImport("get-them-args").getACall()
|
||||
or
|
||||
// `require('minimist')(...)` => `{ _: [], a: ... b: ... }`
|
||||
this = DataFlow::moduleImport("minimist").getACall()
|
||||
or
|
||||
// `require('optimist').argv` => `{ _: [], a: ... b: ... }`
|
||||
this = DataFlow::moduleMember("optimist", "argv")
|
||||
or
|
||||
// `require("arg")({...spec})` => `{_: [], a: ..., b: ...}`
|
||||
this = DataFlow::moduleImport("arg").getACall()
|
||||
or
|
||||
// `(new (require(argparse)).ArgumentParser({...spec})).parse_args()` => `{a: ..., b: ...}`
|
||||
this =
|
||||
API::moduleImport("argparse")
|
||||
.getMember("ArgumentParser")
|
||||
.getInstance()
|
||||
.getMember("parse_args")
|
||||
.getACall()
|
||||
or
|
||||
// `require('command-line-args')({...spec})` => `{a: ..., b: ...}`
|
||||
this = DataFlow::moduleImport("command-line-args").getACall()
|
||||
or
|
||||
// `require('meow')(help, {...spec})` => `{a: ..., b: ....}`
|
||||
this = DataFlow::moduleImport("meow").getACall()
|
||||
or
|
||||
// `require("dashdash").createParser(...spec)` => `{a: ..., b: ...}`
|
||||
this =
|
||||
[
|
||||
API::moduleImport("dashdash"),
|
||||
API::moduleImport("dashdash").getMember("createParser").getReturn()
|
||||
].getMember("parse").getACall()
|
||||
or
|
||||
// `require('commander').myCmdArgumentName`
|
||||
this = commander().getAMember().getAnImmediateUse()
|
||||
or
|
||||
// `require('commander').opt()` => `{a: ..., b: ...}`
|
||||
this = commander().getMember("opts").getACall()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A command line parsing step from `pred` to `succ`.
|
||||
* E.g: `var succ = require("minimist")(pred)`.
|
||||
*/
|
||||
predicate argsParseStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
exists(DataFlow::CallNode call |
|
||||
call = DataFlow::moduleMember("args", "parse").getACall() or
|
||||
call = DataFlow::moduleImport(["yargs-parser", "minimist", "subarg"]).getACall()
|
||||
|
|
||||
succ = call and
|
||||
pred = call.getArgument(0)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A Command instance from the `commander` library.
|
||||
*/
|
||||
private API::Node commander() {
|
||||
result = API::moduleImport("commander")
|
||||
or
|
||||
// `require("commander").program === require("commander")`
|
||||
result = commander().getMember("program")
|
||||
or
|
||||
result = commander().getMember("Command").getInstance()
|
||||
or
|
||||
// lots of chainable methods
|
||||
result = commander().getAMember().getReturn()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an instance of `yargs`.
|
||||
* Either directly imported as a module, or through some chained method call.
|
||||
|
||||
Reference in New Issue
Block a user