@@ -7,6 +7,7 @@ private import codeql.ruby.Concepts
77private import codeql.ruby.ApiGraphs
88private import codeql.ruby.DataFlow
99private import codeql.ruby.frameworks.StandardLibrary
10+ private import codeql.ruby.dataflow.FlowSummary
1011
1112private DataFlow:: Node ioInstanceInstantiation ( ) {
1213 result = API:: getTopLevelMember ( "IO" ) .getAnInstantiation ( ) or
@@ -253,6 +254,47 @@ module File {
253254
254255 override DataFlow:: Node getAPermissionNode ( ) { result = permissionArg }
255256 }
257+
258+ /**
259+ * Flow summary for several methods on the `File` class that propagate taint
260+ * from their first argument to the return value.
261+ */
262+ class FilePathConversionSummary extends SummarizedCallable {
263+ string methodName ;
264+
265+ FilePathConversionSummary ( ) {
266+ methodName = [ "absolute_path" , "dirname" , "expand_path" , "path" , "realdirpath" , "realpath" ] and
267+ this = "File." + methodName
268+ }
269+
270+ override MethodCall getACall ( ) {
271+ result = API:: getTopLevelMember ( "File" ) .getAMethodCall ( methodName ) .asExpr ( ) .getExpr ( )
272+ }
273+
274+ override predicate propagatesFlowExt ( string input , string output , boolean preservesValue ) {
275+ input = "Argument[0]" and
276+ output = "ReturnValue" and
277+ preservesValue = false
278+ }
279+ }
280+
281+ /**
282+ * Flow summary for `File.join`, which propagates taint from every argument to
283+ * its return value.
284+ */
285+ class FileJoinSummary extends SummarizedCallable {
286+ FileJoinSummary ( ) { this = "File.join" }
287+
288+ override MethodCall getACall ( ) {
289+ result = API:: getTopLevelMember ( "File" ) .getAMethodCall ( "join" ) .asExpr ( ) .getExpr ( )
290+ }
291+
292+ override predicate propagatesFlowExt ( string input , string output , boolean preservesValue ) {
293+ input = "Argument[_]" and
294+ output = "ReturnValue" and
295+ preservesValue = false
296+ }
297+ }
256298}
257299
258300/**
0 commit comments