Class: Brakeman::Checks

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

Overview

Collects up results from running different checks.

Checks can be added with Check.add(check_class)

All .rb files in checks/ will be loaded.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = { }) ⇒ Checks

No need to use this directly.


41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/brakeman/checks.rb', line 41

def initialize options = { }
  if options[:min_confidence]
    @min_confidence = options[:min_confidence]
  else
    @min_confidence = Brakeman.get_defaults[:min_confidence]
  end

  @warnings = []
  @template_warnings = []
  @model_warnings = []
  @controller_warnings = []
  @checks_run = []
end

Instance Attribute Details

#checks_runObject (readonly)

Returns the value of attribute checks_run


13
14
15
# File 'lib/brakeman/checks.rb', line 13

def checks_run
  @checks_run
end

#controller_warningsObject (readonly)

Returns the value of attribute controller_warnings


13
14
15
# File 'lib/brakeman/checks.rb', line 13

def controller_warnings
  @controller_warnings
end

#model_warningsObject (readonly)

Returns the value of attribute model_warnings


13
14
15
# File 'lib/brakeman/checks.rb', line 13

def model_warnings
  @model_warnings
end

#template_warningsObject (readonly)

Returns the value of attribute template_warnings


13
14
15
# File 'lib/brakeman/checks.rb', line 13

def template_warnings
  @template_warnings
end

#warningsObject (readonly)

Returns the value of attribute warnings


13
14
15
# File 'lib/brakeman/checks.rb', line 13

def warnings
  @warnings
end

Class Method Details

.add(klass) ⇒ Object

Add a check. This will call klass.new when running tests


16
17
18
# File 'lib/brakeman/checks.rb', line 16

def self.add klass
  @checks << klass unless @checks.include? klass
end

.add_optional(klass) ⇒ Object

Add an optional check


21
22
23
# File 'lib/brakeman/checks.rb', line 21

def self.add_optional klass
  @optional_checks << klass unless @checks.include? klass
end

.checksObject


25
26
27
# File 'lib/brakeman/checks.rb', line 25

def self.checks
  @checks + @optional_checks
end

.initialize_checks(check_directory = "") ⇒ Object


33
34
35
36
37
38
# File 'lib/brakeman/checks.rb', line 33

def self.initialize_checks check_directory = ""
  #Load all files in check_directory
  Dir.glob(File.join(check_directory, "*.rb")).sort.each do |f|
    require f
  end
end

.optional_checksObject


29
30
31
# File 'lib/brakeman/checks.rb', line 29

def self.optional_checks
  @optional_checks
end

.run_checks(app_tree, tracker) ⇒ Object

Run all the checks on the given Tracker. Returns a new instance of Checks with the results.


95
96
97
98
99
100
101
# File 'lib/brakeman/checks.rb', line 95

def self.run_checks(app_tree, tracker)
  if tracker.options[:parallel_checks]
    self.run_checks_parallel(app_tree, tracker)
  else
    self.run_checks_sequential(app_tree, tracker)
  end
end

.run_checks_parallel(app_tree, tracker) ⇒ Object

Run checks in parallel threads


138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/brakeman/checks.rb', line 138

def self.run_checks_parallel(app_tree, tracker)
  threads = []
  error_mutex = Mutex.new

  check_runner = self.new :min_confidence => tracker.options[:min_confidence]

  self.checks_to_run(tracker).each do |c|
    check_name = get_check_name c

    #Run or don't run check based on options
    unless tracker.options[:skip_checks].include? check_name or
      (tracker.options[:run_checks] and not tracker.options[:run_checks].include? check_name)

      Brakeman.notify " - #{check_name}"

      threads << Thread.new do
        check = c.new(app_tree, tracker)

        begin
          check.run_check
        rescue => e
          error_mutex.synchronize do
            tracker.error e
          end
        end

        check.warnings
      end

      #Maintain list of which checks were run
      #mainly for reporting purposes
      check_runner.checks_run << check_name[5..-1]
    end
  end

  threads.each { |t| t.join }

  Brakeman.notify "Checks finished, collecting results..."

  #Collect results
  threads.each do |thread|
    thread.value.each do |warning|
      check_runner.add_warning warning
    end
  end

  check_runner
end

.run_checks_sequential(app_tree, tracker) ⇒ Object

Run checks sequentially


104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/brakeman/checks.rb', line 104

def self.run_checks_sequential(app_tree, tracker)
  check_runner = self.new :min_confidence => tracker.options[:min_confidence]

  self.checks_to_run(tracker).each do |c|
    check_name = get_check_name c

    #Run or don't run check based on options
    unless tracker.options[:skip_checks].include? check_name or
      (tracker.options[:run_checks] and not tracker.options[:run_checks].include? check_name)

      Brakeman.notify " - #{check_name}"

      check = c.new(app_tree, tracker)

      begin
        check.run_check
      rescue => e
        tracker.error e
      end

      check.warnings.each do |w|
        check_runner.add_warning w
      end

      #Maintain list of which checks were run
      #mainly for reporting purposes
      check_runner.checks_run << check_name[5..-1]
    end
  end

  check_runner
end

Instance Method Details

#add_warning(warning) ⇒ Object

Add Warning to list of warnings to report. Warnings are split into four different arrays for template, controller, model, and generic warnings.

Will not add warnings which are below the minimum confidence level.


60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/brakeman/checks.rb', line 60

def add_warning warning
  unless warning.confidence > @min_confidence
    case warning.warning_set
    when :template
      @template_warnings << warning
    when :warning
      @warnings << warning
    when :controller
      @controller_warnings << warning
    when :model
      @model_warnings << warning
    else
      raise "Unknown warning: #{warning.warning_set}"
    end
  end
end

#all_warningsObject

Return an array of all warnings found.


89
90
91
# File 'lib/brakeman/checks.rb', line 89

def all_warnings
  @warnings + @template_warnings + @controller_warnings + @model_warnings
end

#diff(other_checks) ⇒ Object

Return a hash of arrays of new and fixed warnings

diff = checks.diff old_checks
diff[:fixed]  # [...]
diff[:new]    # [...]

82
83
84
85
86
# File 'lib/brakeman/checks.rb', line 82

def diff other_checks
  my_warnings = self.all_warnings
  other_warnings = other_checks.all_warnings
  Brakeman::Differ.new(my_warnings, other_warnings).diff
end