@@ -47,14 +47,70 @@ module IndirectCommandInjection {
4747 // `require('get-them-args')(...)` => `{ unknown: [], a: ... b: ... }`
4848 this = DataFlow:: moduleImport ( "get-them-args" ) .getACall ( )
4949 or
50- // `require('minimist')(...)` => `{ _: [], a: ... b: ... }`
51- this = DataFlow:: moduleImport ( "minimist" ) .getACall ( )
52- or
5350 // `require('optimist').argv` => `{ _: [], a: ... b: ... }`
5451 this = DataFlow:: moduleMember ( "optimist" , "argv" )
52+ or
53+ // `require("arg")({...spec})` => `{_: [], a: ..., b: ...}`
54+ this = DataFlow:: moduleImport ( "arg" ) .getACall ( )
55+ or
56+ // `(new (require(argparse)).ArgumentParser({...spec})).parse_args()` => `{a: ..., b: ...}`
57+ this =
58+ API:: moduleImport ( "argparse" )
59+ .getMember ( "ArgumentParser" )
60+ .getInstance ( )
61+ .getMember ( "parse_args" )
62+ .getACall ( )
63+ or
64+ // `require('command-line-args')({...spec})` => `{a: ..., b: ...}`
65+ this = DataFlow:: moduleImport ( "command-line-args" ) .getACall ( )
66+ or
67+ // `require('meow')(help, {...spec})` => `{a: ..., b: ....}`
68+ this = DataFlow:: moduleImport ( "meow" ) .getACall ( )
69+ or
70+ // `require("dashdash").createParser(...spec)` => `{a: ..., b: ...}`
71+ this =
72+ [
73+ API:: moduleImport ( "dashdash" ) ,
74+ API:: moduleImport ( "dashdash" ) .getMember ( "createParser" ) .getReturn ( )
75+ ] .getMember ( "parse" ) .getACall ( )
76+ or
77+ // `require('commander').myCmdArgumentName`
78+ this = commander ( ) .getAMember ( ) .getAnImmediateUse ( )
79+ or
80+ // `require('commander').opt()` => `{a: ..., b: ...}`
81+ this = commander ( ) .getMember ( "opts" ) .getACall ( )
5582 }
5683 }
5784
85+ /**
86+ * A command line parsing step from `pred` to `succ`.
87+ * E.g: `var succ = require("minimist")(pred)`.
88+ */
89+ predicate argsParseStep ( DataFlow:: Node pred , DataFlow:: Node succ ) {
90+ exists ( DataFlow:: CallNode call |
91+ call = DataFlow:: moduleMember ( "args" , "parse" ) .getACall ( ) or
92+ call = DataFlow:: moduleImport ( [ "yargs-parser" , "minimist" , "subarg" ] ) .getACall ( )
93+ |
94+ succ = call and
95+ pred = call .getArgument ( 0 )
96+ )
97+ }
98+
99+ /**
100+ * A Command instance from the `commander` library.
101+ */
102+ private API:: Node commander ( ) {
103+ result = API:: moduleImport ( "commander" )
104+ or
105+ // `require("commander").program === require("commander")`
106+ result = commander ( ) .getMember ( "program" )
107+ or
108+ result = commander ( ) .getMember ( "Command" ) .getInstance ( )
109+ or
110+ // lots of chainable methods
111+ result = commander ( ) .getAMember ( ) .getReturn ( )
112+ }
113+
58114 /**
59115 * Gets an instance of `yargs`.
60116 * Either directly imported as a module, or through some chained method call.
0 commit comments