Incorrect SQL injection detection. #680

Closed
schneidmaster opened this Issue Jul 9, 2015 · 4 comments

Projects

None yet

4 participants

@schneidmaster

I am having issues with incorrect SQL injection detection within a scope. I reduced it to this trivial example. The Project model has a parent_id attribute and the following scope:

scope :not_child_of, lambda { |project|
  if project.id
    where('parent_id != ?', project.id)
  else
    Project.all
  end
}

For some reason Brakeman is convinced that the Project.all line is a SQL injection vulnerability. Even more bizarrely, the warning disappears if I change Project.all to just all. Am I missing something that makes that line unsafe or is it a bug?

@presidentbeef
Owner

Hi Zach,

I am seeing the same thing, and it is really weird. I'll check it out.

@unmanbearpig

Hi!
I've taken a look at this and I've found something I don't understand, which may be the problem.

It's in find_dangerous_value method in check_sql.rb

    when :call
      unless IGNORE_METHODS_IN_SQL.include? exp.method
        if has_immediate_user_input? exp or has_immediate_model? exp
          exp

I'm don't really understand, why are we checking for has_immediate_model? here?
Judging by the name of the method we're checking if exp is a call on a model class, correct? If so, then I don't get how can it cause SQL injection.

The problem disappears when I delete or has_immediate_model? exp , and the tests still pass.

By the way, I've managed to reduce the example a bit further:

scope :not_a_sql_injection, lambda {
    if true
      Project.hello
    end
  }

It doesn't matter which class method we're calling as long as it's on the model class and inside an if.

@rudywseidinger

+1

Having the same issue here. Slightly different implementation here:

scope :featured, -> (group) do
  if ProductCollection.featured.any?
    ProductCollection.featured.first.products.available_for(group)
  else
    ProductCollection.none
  end
end

It is def related with the condition. Once you get rid of it, it works fine.

@presidentbeef
Owner

This is resolved with #985 and did ultimately use @unmanbearpig's suggestion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment