@@ -8,6 +8,7 @@ private import codeql.ruby.controlflow.CfgNodes
88private import codeql.ruby.DataFlow
99private import codeql.ruby.dataflow.RemoteFlowSources
1010private import codeql.ruby.ApiGraphs
11+ private import codeql.ruby.typetracking.TypeTracking
1112private import codeql.ruby.frameworks.ActionDispatch
1213private import codeql.ruby.frameworks.ActionView
1314private import codeql.ruby.frameworks.Rails
@@ -505,6 +506,27 @@ private module ParamsSummaries {
505506 ]
506507 }
507508
509+ /** Gets a field of an instance of `ActionController::Parameters` */
510+ private DataFlow:: LocalSourceNode paramsField ( ) {
511+ result =
512+ [
513+ paramsInstance ( ) ,
514+ paramsInstance ( ) .getAMethodCall ( methodReturnsTaintFromSelf ( ) ) .getAnElementRead * ( )
515+ ]
516+ }
517+
518+ private DataFlow:: LocalSourceNode paramsFieldType ( TypeTracker t ) {
519+ t .start ( ) and
520+ result = paramsField ( )
521+ or
522+ exists ( TypeTracker t2 | result = paramsFieldType ( t2 ) .track ( t2 , t ) )
523+ }
524+
525+ /** Gets a node with a type that can be a field of `ActionController::Parameters */
526+ private DataFlow:: LocalSourceNode paramsFieldType ( ) {
527+ paramsFieldType ( TypeTracker:: end ( ) ) .flowsTo ( result )
528+ }
529+
508530 /**
509531 * A flow summary for methods on `ActionController::Parameters` which
510532 * propagate taint from receiver to return value.
@@ -569,6 +591,44 @@ private module ParamsSummaries {
569591 preservesValue = false
570592 }
571593 }
594+
595+ /** Flow summaries for `ActiveDispatch::Http::UploadedFile`, which can be an field of `ActionController::Parameters`. */
596+ module UploadedFileSummaries {
597+ /** Flow summary for `ActiveDispatch::Http::UploadedFile.original_filename` */
598+ private class UploadedFileOriginalFilenameSummary extends SummarizedCallable {
599+ UploadedFileOriginalFilenameSummary ( ) {
600+ this = "ActionDispatch::Http::UploadedFile::original_filename"
601+ }
602+
603+ override MethodCall getACall ( ) {
604+ result = paramsFieldType ( ) .getAMethodCall ( "original_filename" ) .asExpr ( ) .getExpr ( ) and
605+ result .getNumberOfArguments ( ) = 0
606+ }
607+
608+ override predicate propagatesFlow ( string input , string output , boolean preservesValue ) {
609+ input = "Argument[self]" and output = "ReturnValue" and preservesValue = false
610+ }
611+ }
612+
613+ /**
614+ * Flow summary for `ActiveDispatch::Http::UploadedFile.original_filename`,
615+ * which propagates taint from the receiver to the return value or to the second (buffer) argument
616+ */
617+ private class UploadedFileReadSummary extends SummarizedCallable {
618+ UploadedFileReadSummary ( ) { this = "ActionDispatch::Http::UploadedFile::read" }
619+
620+ override MethodCall getACall ( ) {
621+ result = paramsFieldType ( ) .getAMethodCall ( "read" ) .asExpr ( ) .getExpr ( ) and
622+ result .getNumberOfArguments ( ) in [ 0 .. 2 ]
623+ }
624+
625+ override predicate propagatesFlow ( string input , string output , boolean preservesValue ) {
626+ input = "Argument[self]" and
627+ output = [ "ReturnValue" , "Argument[1]" ] and
628+ preservesValue = false
629+ }
630+ }
631+ }
572632}
573633
574634/**
0 commit comments