Class: Scryer::Rules::SqlInjectionRule
- Inherits:
-
Scryer::Rule
- Object
- Scryer::Rule
- Scryer::Rules::SqlInjectionRule
- Defined in:
- lib/scryer/rules/sql_injection_rule.rb
Overview
Flags ActiveRecord finder/query methods called with a string argument
that contains interpolation (#...) — the classic Rails SQL injection
pattern, e.g. Order.where("status = '#{params[:status]}'").
Parameterized/hash forms (where(status: params[:status]),
where("status = ?", params[:status])) are safe and not flagged.
Constant Summary collapse
- QUERY_METHODS =
%w[ where find_by find_by! order pluck select group having find_by_sql calculate exists? count ].freeze
Instance Attribute Summary
Attributes inherited from Scryer::Rule
Instance Method Summary collapse
Methods inherited from Scryer::Rule
Constructor Details
This class inherits a constructor from Scryer::Rule
Instance Method Details
#scan ⇒ Object
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/scryer/rules/sql_injection_rule.rb', line 19 def scan findings = [] Ast.each_node(sexp) do |node| next unless Ast.tagged?(node, :method_add_arg, :command, :command_call) receiver_and_name = Ast.call_name(inner_call_node(node)) next unless receiver_and_name _receiver, method_name = receiver_and_name next unless QUERY_METHODS.include?(method_name) args = Ast.call_arguments(node) next if args.empty? first_arg = args.first next unless Ast.string_literal_has_interpolation?(first_arg) line = Ast.line_of(first_arg) || Ast.line_of(node) findings << finding( line: line, message: "`#{method_name}` is called with a string built via interpolation, " \ "which lets user-controlled input change the SQL executed.", suggested_fix: "Use a parameterized form instead, e.g. " \ "`#{method_name}(\"column = ?\", value)` or the hash form " \ "`#{method_name}(column: value)` — both let Active Record escape " \ "the value safely instead of interpolating it directly into SQL." ) end findings end |