@@ -43,28 +43,22 @@ module UnsafeShellCommandConstruction {
43
43
abstract DataFlow:: Node getCommandExecution ( ) ;
44
44
}
45
45
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
-
64
46
/** Holds if the string constructed at `source` is executed at `shellExec` */
65
47
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
+ )
68
62
}
69
63
70
64
/**
0 commit comments