Class: Brakeman::CheckMassAssignment

Inherits:
BaseCheck show all
Defined in:
lib/brakeman/checks/check_mass_assignment.rb

Overview

Checks for mass assignments to models.

See guides.rubyonrails.org/security.html#mass-assignment for details

Constant Summary collapse

LITERALS =

Constants inherited from BaseCheck

BaseCheck::CONFIDENCE

Constants included from Util

Util::ALL_PARAMETERS, Util::COOKIES, Util::PARAMETERS, Util::PATH_PARAMETERS, Util::QUERY_PARAMETERS, Util::REQUEST_ENV, Util::REQUEST_PARAMETERS, Util::REQUEST_PARAMS, Util::SESSION

Constants inherited from SexpProcessor

SexpProcessor::VERSION

Instance Attribute Summary

Attributes inherited from BaseCheck

#tracker, #warnings

Attributes inherited from SexpProcessor

#context, #env, #expected

Instance Method Summary collapse

Methods inherited from BaseCheck

#add_result, #initialize, #process_call, #process_cookies, #process_default, #process_if, #process_params

Methods included from Util

#array?, #call?, #camelize, #contains_class?, #context_for, #cookies?, #false?, #file_by_name, #file_for, #hash?, #hash_access, #hash_insert, #hash_iterate, #integer?, #node_type?, #number?, #params?, #pluralize, #regexp?, #request_env?, #request_value?, #result?, #set_env_defaults, #sexp?, #string?, #symbol?, #table_to_csv, #true?, #truncate_table, #underscore

Methods included from ProcessorHelper

#class_name, #process_all, #process_module

Methods inherited from SexpProcessor

#error_handler, #in_context, #initialize, #process, #process_dummy, #scope

Constructor Details

This class inherits a constructor from Brakeman::BaseCheck

Instance Method Details

#all_literals?(args) ⇒ Boolean

Returns:

  • (Boolean)


96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/brakeman/checks/check_mass_assignment.rb', line 96

def all_literals? args
  args.all? do |arg|
    if sexp? arg
      if arg.node_type == :hash
        all_literals? arg
      else
        LITERALS.include? arg.node_type
      end
    else
      true
    end
  end
end

#check_call(call) ⇒ Object

Want to ignore calls to Model.new that have no arguments



80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/brakeman/checks/check_mass_assignment.rb', line 80

def check_call call
  args = process_all call.args

  if args.empty? #empty new()
    false
  elsif hash? args.first and not include_user_input? args.first
    false
  elsif all_literals? args
    false
  else
    true
  end
end

#process_result(res) ⇒ Object

All results should be Model.new(…) or Model.attributes=() calls



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/brakeman/checks/check_mass_assignment.rb', line 41

def process_result res
  call = res[:call]

  check = check_call call

  if check and not call.original_line and not duplicate? res
    add_result res

    model = tracker.models[res[:chain].first]

    attr_protected = (model and model[:options][:attr_protected])

    if attr_protected and tracker.options[:ignore_attr_protected]
      return
    elsif input = include_user_input?(call.arglist)
      if not hash? call.first_arg and not attr_protected
        confidence = CONFIDENCE[:high]
        user_input = input.match
      else
        confidence = CONFIDENCE[:low]
        user_input = input.match
      end
    else
      confidence = CONFIDENCE[:low]
      user_input = nil
    end
    
    warn :result => res, 
      :warning_type => "Mass Assignment", 
      :message => "Unprotected mass assignment",
      :code => call, 
      :user_input => user_input,
      :confidence => confidence
  end

  res
end

#run_checkObject



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/brakeman/checks/check_mass_assignment.rb', line 12

def run_check
  return if mass_assign_disabled?

  models = []
  tracker.models.each do |name, m|
    if unprotected_model? m
      models << name
    end
  end

  return if models.empty?


  Brakeman.debug "Finding possible mass assignment calls on #{models.length} models"
  calls = tracker.find_call :chained => true, :targets => models, :methods => [:new,
    :attributes=, 
    :update_attributes, 
    :update_attributes!,
    :create,
    :create!,
    :build]

  Brakeman.debug "Processing possible mass assignment calls"
  calls.each do |result|
    process_result result
  end
end