@@ -43,28 +43,22 @@ module UnsafeShellCommandConstruction {
4343 abstract DataFlow:: Node getCommandExecution ( ) ;
4444 }
4545
46- /** A dataflow-configuration for tracking flow from various string constructions to places where those strings are executed as shell commands. */
47- class TrackSystemCommand extends DataFlow2:: Configuration {
48- TrackSystemCommand ( ) { this = "StringConcatAsSink::TrackSystemCommand" }
49-
50- override predicate isSource ( DataFlow:: Node source ) {
51- source instanceof TaintedFormat:: PrintfStyleCall
52- or
53- source .asExpr ( ) .getExpr ( ) =
54- any ( Ast:: StringLiteral lit |
55- lit .getComponent ( _) instanceof Ast:: StringInterpolationComponent
56- )
57- }
58-
59- override predicate isSink ( DataFlow:: Node sink ) {
60- exists ( Concepts:: SystemCommandExecution s | s .isShellInterpreted ( sink ) )
61- }
62- }
63-
6446 /** Holds if the string constructed at `source` is executed at `shellExec` */
6547 predicate isUsedAsShellCommand ( DataFlow:: Node source , Concepts:: SystemCommandExecution shellExec ) {
66- any ( TrackSystemCommand conf )
67- .hasFlow ( source , any ( DataFlow:: Node arg | shellExec .isShellInterpreted ( arg ) ) )
48+ source = backtrackShellExec ( TypeTracker:: TypeBackTracker:: end ( ) , shellExec )
49+ }
50+
51+ import codeql.ruby.typetracking.TypeTracker as TypeTracker
52+
53+ private DataFlow:: LocalSourceNode backtrackShellExec (
54+ TypeTracker:: TypeBackTracker t , Concepts:: SystemCommandExecution shellExec
55+ ) {
56+ t .start ( ) and
57+ result = any ( DataFlow:: Node n | shellExec .isShellInterpreted ( n ) ) .getALocalSource ( )
58+ or
59+ exists ( TypeTracker:: TypeBackTracker t2 |
60+ result = backtrackShellExec ( t2 , shellExec ) .backtrack ( t2 , t )
61+ )
6862 }
6963
7064 /**
0 commit comments