Repository: presidentbeef/brakeman

Issue #1231: False positive: SQL injection through ActiveRecord::ConnectionAdapters::PostgreSQLAdapter#quote
Created: 2018-06-06T22:51:26Z
Background
Brakeman version: 4.2.1
Rails version: 5.2.0
Ruby version: 2.5.0p0 (2017-12-25 revision 61468) [x86_64-darwin17]
False Positive
Full warning from Brakeman:
Confidence: High
Category: SQL Injection
Check: SQL
Message: Possible SQL injection
Code: UserNotification.connection.execute(("INSERT INTO \"user_notifications\" (\"user_id\", \"notification_id\", \"created_at\", \"updated_at\") VALUES " + notifications.map do  notified.map do  (((((((("(" + UserNotification.connection.quote(user.id)) + ", ") + UserNotification.connection.quote(notification.id)) + ", ") + cstime) + ", ") + cstime) + ")")  end.join(", ")  end.join(", ")))
File: app/models/jobs/topology_update_job.rb
Line: 71

Relevant code:
  def assign_notifications
    UserNotification.connection.execute("INSERT INTO \"user_notifications\" (\"user_id\", \"notification_id\", \"created_at\", \"updated_at\") VALUES " +
      notifications.map do |notification|
        notified.map do |user|
          "(" +
          UserNotification.connection.quote(user.id) + ", " +
          UserNotification.connection.quote(notification.id) + ", " +
          cstime + ", " +
          cstime +
          ")"
        end.join(", ")
      end.join(", ")
    )
  end
This is a false positive because the #quote method used here prevents SQL injection.

Duplicate issue #1591: Brakeman doesn't understand `map!`
Created: 2021-05-13T00:36:36Z
Background
Brakeman version: 5.0.1
Rails version: 6.1.3.2
Ruby version: 2.7.3
Link to Rails application code: N/A
Issue
I got a false-positive from Brakeman today that involved a couple layers of incorrect behavior.  One of those layers is somewhat clear and unambiguous, the other is more complex:
pieces = something.underscore.split(".")
pieces.map! { |piece| ActiveRecord::Base.connection.quote_column_name(piece) }
something_clean = pieces.join(".")
some_relation.order(Arel.sql("#{something_clean} #{sort_direction}"))
According to the output from Brakeman, that got reduced to:
Arel.sql("#{something.underscore.split(".").join(".")} #{"asc"}")
Of course, adding map! to the method call chain results in the call to quote_column_name being included in the reduced code as one would expect.
The other, murkier problem:  That doesn't resolve the apparent false-positive, as it seems that Brakeman also doesn't seem to understand quote_column_name -- or at least doesn't understand how I'm using it here.  The change that caused this code to go from passing Brakeman checks to failing them is the change from just doing:
something_clean = ActiveRecord::Base.connection.quote_column_name(something.underscore)
some_relation.order(Arel.sql("#{something_clean} #{sort_direction}"))
So the fundamental problem I'm facing seems to be that joining a set of sanitized values together does not produce what's considered to be a sanitized value.  Maybe that's intended behavior because of the ".", in which case feel free to disregard.
That said, it seems to me that Brakeman not understanding the modify-in-place collection methods does qualify as a defect.  Perhaps a relatively obscure one for most, but those of us using RuboCop checks to help ensure our code isn't too sloppy about performance are gonna get hit by this one (especially since not all the modify-in-place methods actually return the collection in all circumstances -- e.g. uniq! -- making it impossible to reliably used the method-chaining approach with them in some cases).

Closing comment (2021-05-13T00:47:23Z): Ah, I see my second issue is likely the same as #1231 .  Since that doesn't seem like it's going anywhere, I'll plan around that.