Class: RuboCop::Cop::Paraxial::SQL

Inherits:
Base
  • Object
show all
Includes:
ConfigurableEnforcedStyle
Defined in:
lib/rubocop/cop/paraxial/sql.rb

Overview

This cop checks that Active Record queries use literal keys in all of their conditions. Using dynamic keys in queries can make code susceptible to SQL injection attacks.

Examples:

# bad
Model.where("order_count > #{params[:orders]}")
Model.having("order_count > #{params[:orders]}")
Model.exists?("order_count > #{params[:orders]}")

# good
Model.where('order_count > ?', params[:orders])
Model.having('order_count > ?', params[:orders])
Model.exists?('order_count > ?', params[:orders])

EnforcedStyle: params (default)

# bad
Model.find_by(params['id'])

# good
Model.find_by(id: params['id'])
Model.find_by(Group.arel_table[:id].in([1, 2, 3]))

EnforcedStyle: all


# bad
Model.find_by(params['id'])
# Value from Strong Parameters could still cause a SQLi.
Model.find_by(model_params['id'])
# Unfortunately there are false positives too.
Model.find_by(Group.arel_table[:id].in([1, 2, 3]))

# good
Model.find_by(id: params['id'])
Model.find_by(id: model_params['id'])

Constant Summary collapse

MSG =
'SQL injection via dynamic query key.'
RESTRICT_ON_SEND =
%i[
  all
  average
  calculate
  count
  count_by_sql
  create_with
  delete_all
  delete_by
  destroy_all
  destroy_by
  exists?
  find_by
  find_by!
  find_by_sql
  find_or_create_by
  find_or_create_by!
  find_or_initialize_by
  find_or_initialize_by!
  first
  from
  group
  having
  joins
  last
  lock
  maximum
  minimum
  named_scope
  not
  order
  pluck
  reorder
  reselect
  rewhere
  scope
  select
  sql
  sum
  update_all
  where
].freeze

Instance Method Summary collapse

Instance Method Details

#matching_send?(node) ⇒ Boolean

Returns:

  • (Boolean)


102
103
104
# File 'lib/rubocop/cop/paraxial/sql.rb', line 102

def matching_send?(node)
  style == :all ? true : params?(node)
end

#on_send(node) ⇒ Object



106
107
108
109
110
111
112
# File 'lib/rubocop/cop/paraxial/sql.rb', line 106

def on_send(node)
  return if object_manipulation?(node)

  return unless non_literal_condition?(node)

  add_offense(node)
end