@@ -173,7 +173,7 @@ private predicate sqlFragmentArgumentInner(DataFlow::CallNode call, DataFlow::No
173173 "delete_all" , "delete_by" , "destroy_all" , "destroy_by" , "exists?" , "find_by" , "find_by!" ,
174174 "find_or_create_by" , "find_or_create_by!" , "find_or_initialize_by" , "find_by_sql" , "from" ,
175175 "group" , "having" , "joins" , "lock" , "not" , "order" , "reorder" , "pluck" , "where" , "rewhere" ,
176- "select" , "reselect" , "update_all"
176+ "select" , "reselect"
177177 ] ) and
178178 sink = call .getArgument ( 0 )
179179 or
@@ -198,6 +198,20 @@ private predicate sqlFragmentArgumentInner(DataFlow::CallNode call, DataFlow::No
198198 or
199199 call = activeRecordConnectionInstance ( ) .getAMethodCall ( "execute" ) and
200200 sink = call .getArgument ( 0 )
201+ or
202+ call = activeRecordQueryBuilderCall ( "update_all" ) and
203+ (
204+ // `update_all([sink, var1, var2, var3])`
205+ sink = call .getArgument ( 0 ) .getALocalSource ( ) .( DataFlow:: ArrayLiteralNode ) .getElement ( 0 )
206+ or
207+ // or arg0 is not of a known "safe" type
208+ sink = call .getArgument ( 0 ) and
209+ not (
210+ sink .getALocalSource ( ) = any ( DataFlow:: ArrayLiteralNode arr ) or
211+ sink .getALocalSource ( ) = any ( DataFlow:: HashLiteralNode hash ) or
212+ sink .getALocalSource ( ) = any ( DataFlow:: PairNode pair )
213+ )
214+ )
201215}
202216
203217private predicate sqlFragmentArgument ( DataFlow:: CallNode call , DataFlow:: Node sink ) {
0 commit comments