55
66private import python
77private import experimental.dataflow.DataFlow
8+ private import experimental.dataflow.TaintTracking
89private import experimental.dataflow.RemoteFlowSources
910private import experimental.semmle.python.Concepts
1011
12+ /** Provides models for the Python standard library. */
1113private module Stdlib {
1214 /** Gets a reference to the `os` module. */
1315 DataFlow:: Node os ( DataFlow:: TypeTracker t ) {
@@ -20,6 +22,7 @@ private module Stdlib {
2022 /** Gets a reference to the `os` module. */
2123 DataFlow:: Node os ( ) { result = os ( DataFlow:: TypeTracker:: end ( ) ) }
2224
25+ /** Provides models for the `os` module. */
2326 module os {
2427 /** Gets a reference to the `os.system` function. */
2528 DataFlow:: Node system ( DataFlow:: TypeTracker t ) {
@@ -48,6 +51,41 @@ private module Stdlib {
4851
4952 /** Gets a reference to the `os.popen` function. */
5053 DataFlow:: Node popen ( ) { result = os:: popen ( DataFlow:: TypeTracker:: end ( ) ) }
54+
55+ /** Gets a reference to the `os.path` module. */
56+ private DataFlow:: Node path ( DataFlow:: TypeTracker t ) {
57+ t .start ( ) and
58+ (
59+ result = DataFlow:: importMember ( "os" , "path" )
60+ or
61+ result = DataFlow:: importModule ( "os.path" )
62+ )
63+ or
64+ t .startInAttr ( "path" ) and
65+ result = os ( )
66+ or
67+ exists ( DataFlow:: TypeTracker t2 | result = path ( t2 ) .track ( t2 , t ) )
68+ }
69+
70+ /** Gets a reference to the `os.path` module. */
71+ DataFlow:: Node path ( ) { result = path ( DataFlow:: TypeTracker:: end ( ) ) }
72+
73+ /** Provides models for the `os.path` module */
74+ module path {
75+ /** Gets a reference to the `os.path.join` function. */
76+ private DataFlow:: Node join ( DataFlow:: TypeTracker t ) {
77+ t .start ( ) and
78+ result = DataFlow:: importMember ( "os.path" , "join" )
79+ or
80+ t .startInAttr ( "join" ) and
81+ result = os:: path ( )
82+ or
83+ exists ( DataFlow:: TypeTracker t2 | result = join ( t2 ) .track ( t2 , t ) )
84+ }
85+
86+ /** Gets a reference to the `os.join` module. */
87+ DataFlow:: Node join ( ) { result = join ( DataFlow:: TypeTracker:: end ( ) ) }
88+ }
5189 }
5290
5391 /**
@@ -73,4 +111,16 @@ private module Stdlib {
73111 result .asCfgNode ( ) = this .asCfgNode ( ) .( CallNode ) .getArg ( 0 )
74112 }
75113 }
114+
115+ /** An additional taint step for calls to `os.path.join` */
116+ private class OsPathJoinCallAdditionalTaintStep extends TaintTracking:: AdditionalTaintStep {
117+ override predicate step ( DataFlow:: Node nodeFrom , DataFlow:: Node nodeTo ) {
118+ exists ( CallNode call |
119+ nodeTo .asCfgNode ( ) = call and
120+ call .getFunction ( ) = os:: path:: join ( ) .asCfgNode ( ) and
121+ call .getAnArg ( ) = nodeFrom .asCfgNode ( )
122+ )
123+ // TODO: Handle pathlib (like we do for os.path.join)
124+ }
125+ }
76126}
0 commit comments