@@ -71,7 +71,7 @@ private module FabricV1 {
7171 * Provides classes modeling security-relevant aspects of the `fabric` PyPI package, for
7272 * version 2.x.
7373 *
74- * See http://docs.fabfile.org/en/2.5/getting-st arted .html.
74+ * See http://docs.fabfile.org/en/2.5/getting-started .html.
7575 */
7676module FabricV2 {
7777 /** Gets a reference to the `fabric` module. */
@@ -93,56 +93,26 @@ module FabricV2 {
9393 * See https://docs.fabfile.org/en/2.5/api/connection.html#fabric.connection.Connection.
9494 */
9595 module ConnectionClass {
96- /** Gets a reference to the `fabric.connection.Connection` class. */
97- API:: Node classRef ( ) {
98- result = fabric ( ) .getMember ( "Connection" )
99- or
100- result = connection ( ) .getMember ( "Connection" )
101- or
102- result =
103- ModelOutput:: getATypeNode ( "fabric.connection.Connection~Subclass" ) .getASubclass * ( )
104- }
105-
10696 /**
10797 * A source of instances of `fabric.connection.Connection`, extend this class to model new instances.
10898 *
10999 * This can include instantiations of the class, return values from function
110100 * calls, or a special parameter that will be set when functions are called by an external
111101 * library.
112- *
113- * Use the predicate `Connection::instance()` to get references to instances of `fabric.connection.Connection`.
114102 */
115- abstract class InstanceSource extends DataFlow:: LocalSourceNode { }
116-
117- private class ClassInstantiation extends InstanceSource , DataFlow:: CallCfgNode {
118- ClassInstantiation ( ) { this = classRef ( ) .getACall ( ) }
119- }
120-
121- /** Gets a reference to an instance of `fabric.connection.Connection`. */
122- private DataFlow:: TypeTrackingNode instance ( DataFlow:: TypeTracker t ) {
123- t .start ( ) and
124- result instanceof InstanceSource
125- or
126- exists ( DataFlow:: TypeTracker t2 | result = instance ( t2 ) .track ( t2 , t ) )
127- }
128-
129- /** Gets a reference to an instance of `fabric.connection.Connection`. */
130- DataFlow:: Node instance ( ) { instance ( DataFlow:: TypeTracker:: end ( ) ) .flowsTo ( result ) }
103+ abstract class Instance extends DataFlow:: LocalSourceNode { }
131104
132105 /**
133- * Gets a reference to either `run`, `sudo`, or `local` method on a
134- * `fabric.connection.Connection` instance.
135- *
136- * See
137- * - https://docs.fabfile.org/en/2.5/api/connection.html#fabric.connection.Connection.run
138- * - https://docs.fabfile.org/en/2.5/api/connection.html#fabric.connection.Connection.sudo
139- * - https://docs.fabfile.org/en/2.5/api/connection.html#fabric.connection.Connection.local
106+ * A reference to the `fabric.connection.Connection` class.
140107 */
141- private DataFlow:: TypeTrackingNode instanceRunMethods ( DataFlow:: TypeTracker t ) {
142- t .startInAttr ( [ "run" , "sudo" , "local" ] ) and
143- result = instance ( )
144- or
145- exists ( DataFlow:: TypeTracker t2 | result = instanceRunMethods ( t2 ) .track ( t2 , t ) )
108+ class ClassInstantiation extends Instance {
109+ ClassInstantiation ( ) {
110+ this =
111+ [
112+ fabric ( ) .getMember ( "Connection" ) , connection ( ) .getMember ( "Connection" ) ,
113+ ModelOutput:: getATypeNode ( "fabric.connection.Connection~Subclass" ) .getASubclass * ( )
114+ ] .getACall ( )
115+ }
146116 }
147117
148118 /**
@@ -154,8 +124,8 @@ module FabricV2 {
154124 * - https://docs.fabfile.org/en/2.5/api/connection.html#fabric.connection.Connection.sudo
155125 * - https://docs.fabfile.org/en/2.5/api/connection.html#fabric.connection.Connection.local
156126 */
157- DataFlow :: Node instanceRunMethods ( ) {
158- instanceRunMethods ( DataFlow :: TypeTracker :: end ( ) ) . flowsTo ( result )
127+ API :: CallNode instanceRunMethods ( ) {
128+ result = any ( Instance is ) . getAMethodCall ( [ "run" , "sudo" , "local" ] )
159129 }
160130 }
161131 }
@@ -168,19 +138,38 @@ module FabricV2 {
168138 * - https://docs.fabfile.org/en/2.5/api/connection.html#fabric.connection.Connection.local
169139 */
170140 private class FabricConnectionRunSudoLocalCall extends SystemCommandExecution:: Range ,
171- DataFlow :: CallCfgNode
141+ API :: CallNode
172142 {
173143 FabricConnectionRunSudoLocalCall ( ) {
174- this . getFunction ( ) = Fabric:: Connection:: ConnectionClass:: instanceRunMethods ( )
144+ this = Fabric:: Connection:: ConnectionClass:: instanceRunMethods ( )
175145 }
176146
177- override DataFlow:: Node getCommand ( ) {
178- result = [ this .getArg ( 0 ) , this .getArgByName ( "command" ) ]
179- }
147+ override DataFlow:: Node getCommand ( ) { result = this .getParameter ( 0 , "command" ) .asSink ( ) }
180148
181149 override predicate isShellInterpreted ( DataFlow:: Node arg ) { arg = this .getCommand ( ) }
182150 }
183151
152+ /**
153+ * A `gateway` parameter of `fabric.connection.Connection` instance is considered as ssh proxy_command option and can execute command.
154+ * See https://docs.fabfile.org/en/latest/api/connection.html#fabric.connection.Connection
155+ */
156+ private class FabricConnectionProxyCommand extends SystemCommandExecution:: Range , API:: CallNode {
157+ FabricConnectionProxyCommand ( ) {
158+ this instanceof Fabric:: Connection:: ConnectionClass:: Instance and
159+ // we want to make sure that the connection is established otherwise the command of proxy_command won't run.
160+ exists (
161+ this .getAMethodCall ( [
162+ "run" , "get" , "sudo" , "open_gateway" , "open" , "create_session" , "forward_local" ,
163+ "forward_remote" , "put" , "shell" , "sftp"
164+ ] )
165+ )
166+ }
167+
168+ override DataFlow:: Node getCommand ( ) { result = this .getParameter ( 4 , "gateway" ) .asSink ( ) }
169+
170+ override predicate isShellInterpreted ( DataFlow:: Node arg ) { none ( ) }
171+ }
172+
184173 // -------------------------------------------------------------------------
185174 // fabric.tasks
186175 // -------------------------------------------------------------------------
@@ -191,9 +180,12 @@ module FabricV2 {
191180 module Tasks {
192181 /** Gets a reference to the `fabric.tasks.task` decorator. */
193182 API:: Node task ( ) { result in [ tasks ( ) .getMember ( "task" ) , fabric ( ) .getMember ( "task" ) ] }
183+
184+ /** Gets a reference to the `fabric.tasks.task` decorator. */
185+ API:: Node test ( ) { result in [ tasks ( ) .getMember ( "task" ) , fabric ( ) .getMember ( "task" ) ] }
194186 }
195187
196- class FabricTaskFirstParamConnectionInstance extends Fabric:: Connection:: ConnectionClass:: InstanceSource ,
188+ class FabricTaskFirstParamConnectionInstance extends Fabric:: Connection:: ConnectionClass:: Instance ,
197189 DataFlow:: ParameterNode
198190 {
199191 FabricTaskFirstParamConnectionInstance ( ) {
@@ -242,26 +234,27 @@ module FabricV2 {
242234 API:: Node subclassInstance ( ) { result = any ( ModeledSubclass m ) .getASubclass * ( ) .getReturn ( ) }
243235
244236 /**
245- * Gets a reference to the `run` method on an instance of a subclass of `fabric.group.Group`.
237+ * Gets a reference to the `run` and `sudo` methods on an instance of a subclass of `fabric.group.Group`.
246238 *
247239 * See https://docs.fabfile.org/en/2.5/api/group.html#fabric.group.Group.run
240+ * See https://docs.fabfile.org/en/latest/api/group.html#fabric.group.Group.sudo
248241 */
249- API:: Node subclassInstanceRunMethod ( ) { result = subclassInstance ( ) .getMember ( "run" ) }
242+ API:: Node subclassInstanceRunMethod ( ) {
243+ result = subclassInstance ( ) .getMember ( [ "run" , "sudo" ] )
244+ }
250245 }
251246
252247 /**
253248 * A call to `run` on an instance of a subclass of `fabric.group.Group`.
254249 *
255250 * See https://docs.fabfile.org/en/2.5/api/group.html#fabric.group.Group.run
256251 */
257- private class FabricGroupRunCall extends SystemCommandExecution:: Range , DataFlow :: CallCfgNode {
252+ private class FabricGroupRunCall extends SystemCommandExecution:: Range , API :: CallNode {
258253 FabricGroupRunCall ( ) {
259254 this = Fabric:: Group:: GroupClass:: subclassInstanceRunMethod ( ) .getACall ( )
260255 }
261256
262- override DataFlow:: Node getCommand ( ) {
263- result = [ this .getArg ( 0 ) , this .getArgByName ( "command" ) ]
264- }
257+ override DataFlow:: Node getCommand ( ) { result = this .getParameter ( 0 , "command" ) .asSink ( ) }
265258
266259 override predicate isShellInterpreted ( DataFlow:: Node arg ) { arg = this .getCommand ( ) }
267260 }
0 commit comments