@@ -1060,7 +1060,11 @@ private module StdlibPrivate {
10601060 private class OsSystemCall extends SystemCommandExecution:: Range , DataFlow:: CallCfgNode {
10611061 OsSystemCall ( ) { this = os ( ) .getMember ( "system" ) .getACall ( ) }
10621062
1063- override DataFlow:: Node getCommand ( ) { result = this .getArg ( 0 ) }
1063+ override DataFlow:: Node getCommand ( ) {
1064+ result in [ this .getArg ( 0 ) , this .getArgByName ( "command" ) ]
1065+ }
1066+
1067+ override predicate isShellInterpreted ( DataFlow:: Node arg ) { arg = this .getCommand ( ) }
10641068 }
10651069
10661070 /**
@@ -1071,7 +1075,7 @@ private module StdlibPrivate {
10711075 * Although deprecated since version 2.6, they still work in 2.7.
10721076 * See https://docs.python.org/2.7/library/os.html#os.popen2
10731077 */
1074- private class OsPopenCall extends SystemCommandExecution:: Range , DataFlow :: CallCfgNode {
1078+ private class OsPopenCall extends SystemCommandExecution:: Range , API :: CallNode {
10751079 string name ;
10761080
10771081 OsPopenCall ( ) {
@@ -1085,6 +1089,8 @@ private module StdlibPrivate {
10851089 not name = "popen" and
10861090 result = this .getArgByName ( "cmd" )
10871091 }
1092+
1093+ override predicate isShellInterpreted ( DataFlow:: Node arg ) { arg = this .getCommand ( ) }
10881094 }
10891095
10901096 /**
@@ -1103,6 +1109,10 @@ private module StdlibPrivate {
11031109 override DataFlow:: Node getCommand ( ) { result = this .getArg ( 0 ) }
11041110
11051111 override DataFlow:: Node getAPathArgument ( ) { result = this .getCommand ( ) }
1112+
1113+ override predicate isShellInterpreted ( DataFlow:: Node arg ) {
1114+ none ( ) // this is a safe API.
1115+ }
11061116 }
11071117
11081118 /**
@@ -1129,6 +1139,10 @@ private module StdlibPrivate {
11291139 }
11301140
11311141 override DataFlow:: Node getAPathArgument ( ) { result = this .getCommand ( ) }
1142+
1143+ override predicate isShellInterpreted ( DataFlow:: Node arg ) {
1144+ none ( ) // this is a safe API.
1145+ }
11321146 }
11331147
11341148 /**
@@ -1142,6 +1156,10 @@ private module StdlibPrivate {
11421156 override DataFlow:: Node getCommand ( ) { result in [ this .getArg ( 0 ) , this .getArgByName ( "path" ) ] }
11431157
11441158 override DataFlow:: Node getAPathArgument ( ) { result = this .getCommand ( ) }
1159+
1160+ override predicate isShellInterpreted ( DataFlow:: Node arg ) {
1161+ none ( ) // this is a safe API.
1162+ }
11451163 }
11461164
11471165 /** An additional taint step for calls to `os.path.join` */
@@ -1186,6 +1204,7 @@ private module StdlibPrivate {
11861204 }
11871205
11881206 private boolean get_shell_arg_value ( ) {
1207+ // TODO: API-node this thing - with added tests for unsafe-shell-command-construction
11891208 not exists ( this .get_shell_arg ( ) ) and
11901209 result = false
11911210 or
@@ -1239,6 +1258,11 @@ private module StdlibPrivate {
12391258 )
12401259 )
12411260 }
1261+
1262+ override predicate isShellInterpreted ( DataFlow:: Node arg ) {
1263+ arg = this .get_executable_arg ( ) and
1264+ this .get_shell_arg_value ( ) = true
1265+ }
12421266 }
12431267
12441268 // ---------------------------------------------------------------------------
@@ -1385,6 +1409,8 @@ private module StdlibPrivate {
13851409 }
13861410
13871411 override DataFlow:: Node getCommand ( ) { result in [ this .getArg ( 0 ) , this .getArgByName ( "cmd" ) ] }
1412+
1413+ override predicate isShellInterpreted ( DataFlow:: Node arg ) { arg = this .getCommand ( ) }
13881414 }
13891415
13901416 // ---------------------------------------------------------------------------
@@ -1401,6 +1427,8 @@ private module StdlibPrivate {
14011427 PlatformPopenCall ( ) { this = platform ( ) .getMember ( "popen" ) .getACall ( ) }
14021428
14031429 override DataFlow:: Node getCommand ( ) { result in [ this .getArg ( 0 ) , this .getArgByName ( "cmd" ) ] }
1430+
1431+ override predicate isShellInterpreted ( DataFlow:: Node arg ) { arg = this .getCommand ( ) }
14041432 }
14051433
14061434 // ---------------------------------------------------------------------------
0 commit comments