brakeman 3.4.0 → 3.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +10 -0
  3. data/bundle/load.rb +3 -3
  4. data/bundle/ruby/2.3.0/gems/{ruby2ruby-2.3.0 → ruby2ruby-2.3.1}/History.txt +10 -0
  5. data/bundle/ruby/2.3.0/gems/{ruby2ruby-2.3.0 → ruby2ruby-2.3.1}/Manifest.txt +0 -0
  6. data/bundle/ruby/2.3.0/gems/{ruby2ruby-2.3.0 → ruby2ruby-2.3.1}/README.txt +0 -0
  7. data/bundle/ruby/2.3.0/gems/{ruby2ruby-2.3.0 → ruby2ruby-2.3.1}/Rakefile +0 -0
  8. data/bundle/ruby/2.3.0/gems/{ruby2ruby-2.3.0 → ruby2ruby-2.3.1}/bin/r2r_show +0 -0
  9. data/bundle/ruby/2.3.0/gems/{ruby2ruby-2.3.0 → ruby2ruby-2.3.1}/lib/ruby2ruby.rb +34 -1
  10. data/bundle/ruby/2.3.0/gems/{ruby2ruby-2.3.0 → ruby2ruby-2.3.1}/test/test_ruby2ruby.rb +41 -0
  11. data/bundle/ruby/2.3.0/gems/{ruby_parser-3.8.2 → ruby_parser-3.8.3}/History.txt +12 -0
  12. data/bundle/ruby/2.3.0/gems/{ruby_parser-3.8.2 → ruby_parser-3.8.3}/Manifest.txt +0 -0
  13. data/bundle/ruby/2.3.0/gems/{ruby_parser-3.8.2 → ruby_parser-3.8.3}/README.txt +0 -0
  14. data/bundle/ruby/2.3.0/gems/{ruby_parser-3.8.2 → ruby_parser-3.8.3}/Rakefile +0 -0
  15. data/bundle/ruby/2.3.0/gems/{ruby_parser-3.8.2 → ruby_parser-3.8.3}/bin/ruby_parse +0 -0
  16. data/bundle/ruby/2.3.0/gems/{ruby_parser-3.8.2 → ruby_parser-3.8.3}/bin/ruby_parse_extract_error +0 -0
  17. data/bundle/ruby/2.3.0/gems/{ruby_parser-3.8.2 → ruby_parser-3.8.3}/lib/ruby18_parser.rb +7 -8
  18. data/bundle/ruby/2.3.0/gems/{ruby_parser-3.8.2 → ruby_parser-3.8.3}/lib/ruby18_parser.y +7 -8
  19. data/bundle/ruby/2.3.0/gems/{ruby_parser-3.8.2 → ruby_parser-3.8.3}/lib/ruby19_parser.rb +8 -9
  20. data/bundle/ruby/2.3.0/gems/{ruby_parser-3.8.2 → ruby_parser-3.8.3}/lib/ruby19_parser.y +10 -11
  21. data/bundle/ruby/2.3.0/gems/ruby_parser-3.8.3/lib/ruby20_parser.rb +6690 -0
  22. data/bundle/ruby/2.3.0/gems/{ruby_parser-3.8.2 → ruby_parser-3.8.3}/lib/ruby20_parser.y +14 -50
  23. data/bundle/ruby/2.3.0/gems/ruby_parser-3.8.3/lib/ruby21_parser.rb +6738 -0
  24. data/bundle/ruby/2.3.0/gems/{ruby_parser-3.8.2 → ruby_parser-3.8.3}/lib/ruby21_parser.y +14 -48
  25. data/bundle/ruby/2.3.0/gems/{ruby_parser-3.8.2 → ruby_parser-3.8.3}/lib/ruby22_parser.rb +263 -286
  26. data/bundle/ruby/2.3.0/gems/{ruby_parser-3.8.2 → ruby_parser-3.8.3}/lib/ruby22_parser.y +14 -45
  27. data/bundle/ruby/2.3.0/gems/{ruby_parser-3.8.2 → ruby_parser-3.8.3}/lib/ruby23_parser.rb +269 -292
  28. data/bundle/ruby/2.3.0/gems/{ruby_parser-3.8.2 → ruby_parser-3.8.3}/lib/ruby23_parser.y +14 -45
  29. data/bundle/ruby/2.3.0/gems/{ruby_parser-3.8.2 → ruby_parser-3.8.3}/lib/ruby_lexer.rb +41 -8
  30. data/bundle/ruby/2.3.0/gems/{ruby_parser-3.8.2 → ruby_parser-3.8.3}/lib/ruby_lexer.rex +6 -6
  31. data/bundle/ruby/2.3.0/gems/{ruby_parser-3.8.2 → ruby_parser-3.8.3}/lib/ruby_lexer.rex.rb +17 -11
  32. data/bundle/ruby/2.3.0/gems/{ruby_parser-3.8.2 → ruby_parser-3.8.3}/lib/ruby_parser.rb +0 -0
  33. data/bundle/ruby/2.3.0/gems/{ruby_parser-3.8.2 → ruby_parser-3.8.3}/lib/ruby_parser.yy +20 -33
  34. data/bundle/ruby/2.3.0/gems/{ruby_parser-3.8.2 → ruby_parser-3.8.3}/lib/ruby_parser_extras.rb +65 -3
  35. data/bundle/ruby/2.3.0/gems/{ruby_parser-3.8.2 → ruby_parser-3.8.3}/test/test_ruby_lexer.rb +88 -14
  36. data/bundle/ruby/2.3.0/gems/{ruby_parser-3.8.2 → ruby_parser-3.8.3}/test/test_ruby_parser.rb +102 -9
  37. data/bundle/ruby/2.3.0/gems/{ruby_parser-3.8.2 → ruby_parser-3.8.3}/test/test_ruby_parser_extras.rb +1 -1
  38. data/bundle/ruby/2.3.0/gems/{terminal-table-1.7.1 → terminal-table-1.7.3}/Gemfile +2 -0
  39. data/bundle/ruby/2.3.0/gems/{terminal-table-1.7.1 → terminal-table-1.7.3}/History.rdoc +10 -0
  40. data/bundle/ruby/2.3.0/gems/{terminal-table-1.7.1 → terminal-table-1.7.3}/Manifest +0 -0
  41. data/bundle/ruby/2.3.0/gems/{terminal-table-1.7.1 → terminal-table-1.7.3}/README.rdoc +0 -0
  42. data/bundle/ruby/2.3.0/gems/terminal-table-1.7.3/Rakefile +15 -0
  43. data/bundle/ruby/2.3.0/gems/{terminal-table-1.7.1 → terminal-table-1.7.3}/Todo.rdoc +0 -0
  44. data/bundle/ruby/2.3.0/gems/{terminal-table-1.7.1 → terminal-table-1.7.3}/examples/examples.rb +0 -0
  45. data/bundle/ruby/2.3.0/gems/{terminal-table-1.7.1 → terminal-table-1.7.3}/lib/terminal-table.rb +0 -0
  46. data/bundle/ruby/2.3.0/gems/{terminal-table-1.7.1 → terminal-table-1.7.3}/lib/terminal-table/cell.rb +0 -0
  47. data/bundle/ruby/2.3.0/gems/{terminal-table-1.7.1 → terminal-table-1.7.3}/lib/terminal-table/import.rb +0 -0
  48. data/bundle/ruby/2.3.0/gems/{terminal-table-1.7.1 → terminal-table-1.7.3}/lib/terminal-table/row.rb +4 -0
  49. data/bundle/ruby/2.3.0/gems/{terminal-table-1.7.1 → terminal-table-1.7.3}/lib/terminal-table/separator.rb +0 -0
  50. data/bundle/ruby/2.3.0/gems/{terminal-table-1.7.1 → terminal-table-1.7.3}/lib/terminal-table/style.rb +9 -0
  51. data/bundle/ruby/2.3.0/gems/terminal-table-1.7.3/lib/terminal-table/table.rb +343 -0
  52. data/bundle/ruby/2.3.0/gems/{terminal-table-1.7.1 → terminal-table-1.7.3}/lib/terminal-table/table_helper.rb +0 -0
  53. data/bundle/ruby/2.3.0/gems/{terminal-table-1.7.1 → terminal-table-1.7.3}/lib/terminal-table/version.rb +1 -1
  54. data/bundle/ruby/2.3.0/gems/{terminal-table-1.7.1 → terminal-table-1.7.3}/terminal-table.gemspec +0 -0
  55. data/lib/brakeman.rb +2 -1
  56. data/lib/brakeman/app_tree.rb +22 -5
  57. data/lib/brakeman/checks/check_forgery_setting.rb +43 -31
  58. data/lib/brakeman/checks/check_link_to_href.rb +33 -19
  59. data/lib/brakeman/checks/check_sql.rb +3 -1
  60. data/lib/brakeman/checks/check_symbol_dos.rb +1 -0
  61. data/lib/brakeman/checks/check_unsafe_reflection.rb +1 -1
  62. data/lib/brakeman/options.rb +5 -0
  63. data/lib/brakeman/processors/gem_processor.rb +17 -10
  64. data/lib/brakeman/report/ignore/interactive.rb +17 -6
  65. data/lib/brakeman/scanner.rb +4 -0
  66. data/lib/brakeman/tracker/config.rb +10 -1
  67. data/lib/brakeman/version.rb +1 -1
  68. metadata +53 -53
  69. data/bundle/ruby/2.3.0/gems/ruby_parser-3.8.2/lib/ruby20_parser.rb +0 -6728
  70. data/bundle/ruby/2.3.0/gems/ruby_parser-3.8.2/lib/ruby21_parser.rb +0 -6766
  71. data/bundle/ruby/2.3.0/gems/terminal-table-1.7.1/Rakefile +0 -9
  72. data/bundle/ruby/2.3.0/gems/terminal-table-1.7.1/lib/terminal-table/table.rb +0 -239
@@ -62,6 +62,15 @@ module Terminal
62
62
  @@defaults = defaults.merge(options)
63
63
  end
64
64
  end
65
+
66
+ def on_change attr
67
+ method_name = :"#{attr}="
68
+ old_method = method method_name
69
+ define_singleton_method(method_name) do |value|
70
+ old_method.call value
71
+ yield attr.to_sym, value
72
+ end
73
+ end
65
74
  end
66
75
  end
67
76
  end
@@ -0,0 +1,343 @@
1
+ require 'unicode/display_width'
2
+
3
+ module Terminal
4
+ class Table
5
+
6
+ attr_reader :title
7
+ attr_reader :headings
8
+
9
+ ##
10
+ # Generates a ASCII table with the given _options_.
11
+
12
+ def initialize options = {}, &block
13
+ @headings = []
14
+ @rows = []
15
+ @column_widths = []
16
+ self.style = options.fetch :style, {}
17
+ self.headings = options.fetch :headings, []
18
+ self.rows = options.fetch :rows, []
19
+ self.title = options.fetch :title, nil
20
+ yield_or_eval(&block) if block
21
+
22
+ style.on_change(:width) { require_column_widths_recalc }
23
+ end
24
+
25
+ ##
26
+ # Align column _n_ to the given _alignment_ of :center, :left, or :right.
27
+
28
+ def align_column n, alignment
29
+ r = rows
30
+ column(n).each_with_index do |col, i|
31
+ cell = r[i][n]
32
+ cell.alignment = alignment unless cell.alignment?
33
+ end
34
+ end
35
+
36
+ ##
37
+ # Add a row.
38
+
39
+ def add_row array
40
+ row = array == :separator ? Separator.new(self) : Row.new(self, array)
41
+ @rows << row
42
+ require_column_widths_recalc unless row.is_a?(Separator)
43
+ end
44
+ alias :<< :add_row
45
+
46
+ ##
47
+ # Add a separator.
48
+
49
+ def add_separator
50
+ self << :separator
51
+ end
52
+
53
+ def cell_spacing
54
+ cell_padding + style.border_y.length
55
+ end
56
+
57
+ def cell_padding
58
+ style.padding_left + style.padding_right
59
+ end
60
+
61
+ ##
62
+ # Return column _n_.
63
+
64
+ def column n, method = :value, array = rows
65
+ array.map { |row|
66
+ # for each cells in a row, find the column with index
67
+ # just greater than the required one, and go back one.
68
+ index = col = 0
69
+ row.cells.each do |cell|
70
+ break if index > n
71
+ index += cell.colspan
72
+ col += 1
73
+ end
74
+ cell = row[col - 1]
75
+ cell && method ? cell.__send__(method) : cell
76
+ }.compact
77
+ end
78
+
79
+ ##
80
+ # Return _n_ column including headings.
81
+
82
+ def column_with_headings n, method = :value
83
+ column n, method, headings_with_rows
84
+ end
85
+
86
+ ##
87
+ # Return columns.
88
+
89
+ def columns
90
+ (0...number_of_columns).map { |n| column n }
91
+ end
92
+
93
+ ##
94
+ # Return length of column _n_.
95
+
96
+ def column_width n
97
+ width = column_widths[n] || 0
98
+ end
99
+ alias length_of_column column_width # for legacy support
100
+
101
+ ##
102
+ # Return total number of columns available.
103
+
104
+ def number_of_columns
105
+ headings_with_rows.map { |r| r.number_of_columns }.max || 0
106
+ end
107
+
108
+ ##
109
+ # Set the headings
110
+
111
+ def headings= arrays
112
+ arrays = [arrays] unless arrays.first.is_a?(Array)
113
+ @headings = arrays.map do |array|
114
+ row = Row.new(self, array)
115
+ require_column_widths_recalc
116
+ row
117
+ end
118
+ end
119
+
120
+ ##
121
+ # Render the table.
122
+
123
+ def render
124
+ separator = Separator.new(self)
125
+ buffer = [separator]
126
+ unless @title.nil?
127
+ buffer << Row.new(self, [title_cell_options])
128
+ buffer << separator
129
+ end
130
+ @headings.each do |row|
131
+ unless row.cells.empty?
132
+ buffer << row
133
+ buffer << separator
134
+ end
135
+ end
136
+ if style.all_separators
137
+ buffer += @rows.product([separator]).flatten
138
+ else
139
+ buffer += @rows
140
+ buffer << separator
141
+ end
142
+ buffer.map { |r| style.margin_left + r.render.rstrip }.join("\n")
143
+ end
144
+ alias :to_s :render
145
+
146
+ ##
147
+ # Return rows without separator rows.
148
+
149
+ def rows
150
+ @rows.reject { |row| row.is_a? Separator }
151
+ end
152
+
153
+ def rows= array
154
+ @rows = []
155
+ array.each { |arr| self << arr }
156
+ end
157
+
158
+ def style=(options)
159
+ style.apply options
160
+ end
161
+
162
+ def style
163
+ @style ||= Style.new
164
+ end
165
+
166
+ def title=(title)
167
+ @title = title
168
+ require_column_widths_recalc
169
+ end
170
+
171
+ ##
172
+ # Check if _other_ is equal to self. _other_ is considered equal
173
+ # if it contains the same headings and rows.
174
+
175
+ def == other
176
+ if other.respond_to? :render and other.respond_to? :rows
177
+ self.headings == other.headings and self.rows == other.rows
178
+ end
179
+ end
180
+
181
+ private
182
+
183
+ def columns_width
184
+ column_widths.inject(0) { |s, i| s + i + cell_spacing } + style.border_y.length
185
+ end
186
+
187
+ def recalc_column_widths
188
+ @require_column_widths_recalc = false
189
+ n_cols = number_of_columns
190
+ space_width = cell_spacing
191
+ return if n_cols == 0
192
+
193
+ # prepare rows
194
+ all_rows = headings_with_rows
195
+ all_rows << Row.new(self, [title_cell_options]) unless @title.nil?
196
+
197
+ # DP states, dp[colspan][index][split_offset] => column_width.
198
+ dp = []
199
+
200
+ # prepare initial value for DP.
201
+ all_rows.each do |row|
202
+ index = 0
203
+ row.cells.each do |cell|
204
+ cell_value = cell.value_for_column_width_recalc
205
+ cell_width = Unicode::DisplayWidth.of(cell_value.to_s)
206
+ colspan = cell.colspan
207
+
208
+ # find column width from each single cell.
209
+ dp[colspan] ||= []
210
+ dp[colspan][index] ||= [0] # add a fake cell with length 0.
211
+ dp[colspan][index][colspan] ||= 0 # initialize column length to 0.
212
+
213
+ # the last index `colspan` means width of the single column (split
214
+ # at end of each column), not a width made up of multiple columns.
215
+ single_column_length = [cell_width, dp[colspan][index][colspan]].max
216
+ dp[colspan][index][colspan] = single_column_length
217
+
218
+ index += colspan
219
+ end
220
+ end
221
+
222
+ # run DP.
223
+ (1..n_cols).each do |colspan|
224
+ dp[colspan] ||= []
225
+ (0..n_cols-colspan).each do |index|
226
+ dp[colspan][index] ||= [1]
227
+ (1...colspan).each do |offset|
228
+ # processed level became reverse map from width => [offset, ...].
229
+ left_colspan = offset
230
+ left_index = index
231
+ left_width = dp[left_colspan][left_index].keys.first
232
+
233
+ right_colspan = colspan - left_colspan
234
+ right_index = index + offset
235
+ right_width = dp[right_colspan][right_index].keys.first
236
+
237
+ dp[colspan][index][offset] = left_width + right_width + space_width
238
+ end
239
+
240
+ # reverse map it for resolution (max width and short offset first).
241
+ rmap = {}
242
+ dp[colspan][index].each_with_index do |width, offset|
243
+ rmap[width] ||= []
244
+ rmap[width] << offset
245
+ end
246
+
247
+ # sort reversely and store it back.
248
+ dp[colspan][index] = Hash[rmap.sort.reverse]
249
+ end
250
+ end
251
+
252
+ resolve = lambda do |colspan, full_width, index = 0|
253
+ # stop if reaches the bottom level.
254
+ return @column_widths[index] = full_width if colspan == 1
255
+
256
+ # choose best split offset for partition, or second best result
257
+ # if first one is not dividable.
258
+ candidate_offsets = dp[colspan][index].collect(&:last).flatten
259
+ offset = candidate_offsets[0]
260
+ offset = candidate_offsets[1] if offset == colspan
261
+
262
+ # prepare for next round.
263
+ left_colspan = offset
264
+ left_index = index
265
+ left_width = dp[left_colspan][left_index].keys.first
266
+
267
+ right_colspan = colspan - left_colspan
268
+ right_index = index + offset
269
+ right_width = dp[right_colspan][right_index].keys.first
270
+
271
+ # calculate reference column width, give remaining spaces to left.
272
+ total_non_space_width = full_width - (colspan - 1) * space_width
273
+ ref_column_width = total_non_space_width / colspan
274
+ remainder = total_non_space_width % colspan
275
+ rem_left_width = [remainder, left_colspan].min
276
+ rem_right_width = remainder - rem_left_width
277
+ ref_left_width = ref_column_width * left_colspan +
278
+ (left_colspan - 1) * space_width + rem_left_width
279
+ ref_right_width = ref_column_width * right_colspan +
280
+ (right_colspan - 1) * space_width + rem_right_width
281
+
282
+ # at most one width can be greater than the reference width.
283
+ if left_width <= ref_left_width and right_width <= ref_right_width
284
+ # use refernce width (evenly partition).
285
+ left_width = ref_left_width
286
+ right_width = ref_right_width
287
+ else
288
+ # the wider one takes its value, shorter one takes the rest.
289
+ if left_width > ref_left_width
290
+ right_width = full_width - left_width - space_width
291
+ else
292
+ left_width = full_width - right_width - space_width
293
+ end
294
+ end
295
+
296
+ # run next round.
297
+ resolve.call(left_colspan, left_width, left_index)
298
+ resolve.call(right_colspan, right_width, right_index)
299
+ end
300
+
301
+ full_width = dp[n_cols][0].keys.first
302
+ unless style.width.nil?
303
+ new_width = style.width - space_width - style.border_y.length
304
+ if new_width < full_width
305
+ raise "Table width exceeds wanted width " +
306
+ "of #{style.width} characters."
307
+ end
308
+ full_width = new_width
309
+ end
310
+
311
+ resolve.call(n_cols, full_width)
312
+ end
313
+
314
+ ##
315
+ # Return headings combined with rows.
316
+
317
+ def headings_with_rows
318
+ @headings + rows
319
+ end
320
+
321
+ def yield_or_eval &block
322
+ return unless block
323
+ if block.arity > 0
324
+ yield self
325
+ else
326
+ self.instance_eval(&block)
327
+ end
328
+ end
329
+
330
+ def title_cell_options
331
+ {:value => @title, :alignment => :center, :colspan => number_of_columns}
332
+ end
333
+
334
+ def require_column_widths_recalc
335
+ @require_column_widths_recalc = true
336
+ end
337
+
338
+ def column_widths
339
+ recalc_column_widths if @require_column_widths_recalc
340
+ @column_widths
341
+ end
342
+ end
343
+ end
@@ -1,5 +1,5 @@
1
1
  module Terminal
2
2
  class Table
3
- VERSION = '1.7.1'
3
+ VERSION = '1.7.3'
4
4
  end
5
5
  end
@@ -146,7 +146,8 @@ module Brakeman
146
146
  :relative_path => false,
147
147
  :report_progress => true,
148
148
  :html_style => "#{File.expand_path(File.dirname(__FILE__))}/brakeman/format/style.css",
149
- :output_color => true
149
+ :output_color => true,
150
+ :engine_paths => ["engines/*"]
150
151
  }
151
152
  end
152
153
 
@@ -19,6 +19,7 @@ module Brakeman
19
19
  init_options[:only_files] = regex_for_paths(options[:only_files])
20
20
  end
21
21
  init_options[:additional_libs_path] = options[:additional_libs_path]
22
+ init_options[:engine_paths] = options[:engine_paths]
22
23
  new(root, init_options)
23
24
  end
24
25
 
@@ -57,6 +58,9 @@ module Brakeman
57
58
  @skip_files = init_options[:skip_files]
58
59
  @only_files = init_options[:only_files]
59
60
  @additional_libs_path = init_options[:additional_libs_path] || []
61
+ @engine_paths = init_options[:engine_paths] || []
62
+ @absolute_engine_paths = @engine_paths.select { |path| path.start_with?(File::SEPARATOR) }
63
+ @relative_engine_paths = @engine_paths - @absolute_engine_paths
60
64
  end
61
65
 
62
66
  def expand_path(path)
@@ -101,8 +105,7 @@ module Brakeman
101
105
  end
102
106
 
103
107
  def layout_exists?(name)
104
- pattern = "#{@root}/{engines/*/,}app/views/layouts/#{name}.html.{erb,haml,slim}"
105
- !Dir.glob(pattern).empty?
108
+ !Dir.glob("#{root_search_pattern}app/views/layouts/#{name}.html.{erb,haml,slim}").empty?
106
109
  end
107
110
 
108
111
  def lib_paths
@@ -121,10 +124,14 @@ module Brakeman
121
124
  @additional_libs_path.collect{ |path| find_paths path }.flatten
122
125
  end
123
126
 
124
- def find_paths(directory, extensions = "*.rb")
125
- pattern = @root + "/{engines/*/,}#{directory}/**/#{extensions}"
127
+ def find_paths(directory, extensions = ".rb")
128
+ select_files(glob_files(directory, "*", extensions).sort)
129
+ end
130
+
131
+ def glob_files(directory, name, extensions = ".rb")
132
+ pattern = "#{root_search_pattern}#{directory}/**/#{name}#{extensions}"
126
133
 
127
- select_files(Dir.glob(pattern).sort)
134
+ Dir.glob(pattern)
128
135
  end
129
136
 
130
137
  def select_files(paths)
@@ -160,5 +167,15 @@ module Brakeman
160
167
 
161
168
  files.match(project_relative_path)
162
169
  end
170
+
171
+ def root_search_pattern
172
+ return @root_search_pattern if @root_search_pattern
173
+ abs = @absolute_engine_paths.to_a.map { |path| path.gsub /#{File::SEPARATOR}+$/, '' }
174
+ rel = @relative_engine_paths.to_a.map { |path| path.gsub /#{File::SEPARATOR}+$/, '' }
175
+
176
+ roots = ([@root] + abs).join(",")
177
+ rel_engines = (rel + [""]).join("/,")
178
+ @root_search_patrern = "{#{roots}}/{#{rel_engines}}"
179
+ end
163
180
  end
164
181
  end
@@ -7,41 +7,41 @@ require 'brakeman/checks/base_check'
7
7
  class Brakeman::CheckForgerySetting < Brakeman::BaseCheck
8
8
  Brakeman::Checks.add self
9
9
 
10
- @description = "Verifies that protect_from_forgery is enabled in ApplicationController"
10
+ @description = "Verifies that protect_from_forgery is enabled in direct subclasses of ActionController::Base"
11
11
 
12
12
  def run_check
13
- app_controller = tracker.controllers[:ApplicationController]
14
- return unless app_controller and app_controller.ancestor? :"ActionController::Base"
15
-
16
- if tracker.config.allow_forgery_protection?
17
- csrf_warning :warning_code => :csrf_protection_disabled,
18
- :message => "Forgery protection is disabled"
19
-
20
- elsif app_controller and not app_controller.protect_from_forgery?
21
- csrf_warning :warning_code => :csrf_protection_missing,
22
- :message => "'protect_from_forgery' should be called in ApplicationController",
23
- :line => app_controller.top_line
24
-
25
- elsif version_between? "2.1.0", "2.3.10"
26
- cve_2011_0447 "2.3.11"
27
-
28
- elsif version_between? "3.0.0", "3.0.3"
29
- cve_2011_0447 "3.0.4"
30
-
31
- elsif version_between? "4.0.0", "100.0.0" and forgery_opts = app_controller.options[:protect_from_forgery]
32
- unless forgery_opts.is_a?(Array) and sexp?(forgery_opts.first) and
13
+ tracker.controllers
14
+ .select { |_, controller| controller.parent == :"ActionController::Base" }
15
+ .each do |name, controller|
16
+ if controller and not controller.protect_from_forgery?
17
+ csrf_warning :controller => name,
18
+ :warning_code => :csrf_protection_missing,
19
+ :message => "'protect_from_forgery' should be called in #{name}",
20
+ :file => controller.file,
21
+ :line => controller.top_line
22
+ elsif version_between? "4.0.0", "100.0.0" and forgery_opts = controller.options[:protect_from_forgery]
23
+ unless forgery_opts.is_a?(Array) and sexp?(forgery_opts.first) and
33
24
  access_arg = hash_access(forgery_opts.first.first_arg, :with) and symbol? access_arg and
34
25
  access_arg.value == :exception
35
26
 
36
- args = {
37
- :warning_code => :csrf_not_protected_by_raising_exception,
38
- :message => "protect_from_forgery should be configured with 'with: :exception'",
39
- :confidence => CONFIDENCE[:med]
40
- }
27
+ args = {
28
+ :controller => name,
29
+ :warning_type => "Cross-Site Request Forgery",
30
+ :warning_code => :csrf_not_protected_by_raising_exception,
31
+ :message => "protect_from_forgery should be configured with 'with: :exception'",
32
+ :confidence => CONFIDENCE[:med],
33
+ :file => controller.file
34
+ }
35
+
36
+ args.merge!(:code => forgery_opts.first) if forgery_opts.is_a?(Array)
41
37
 
42
- args.merge!(:code => forgery_opts.first) if forgery_opts.is_a?(Array)
38
+ csrf_warning args
39
+ end
43
40
 
44
- csrf_warning args
41
+ end
42
+
43
+ if controller.options[:protect_from_forgery]
44
+ check_cve_2011_0447
45
45
  end
46
46
  end
47
47
  end
@@ -50,14 +50,26 @@ class Brakeman::CheckForgerySetting < Brakeman::BaseCheck
50
50
  opts = {
51
51
  :controller => :ApplicationController,
52
52
  :warning_type => "Cross-Site Request Forgery",
53
- :confidence => CONFIDENCE[:high],
54
- :file => tracker.controllers[:ApplicationController].file
53
+ :confidence => CONFIDENCE[:high]
55
54
  }.merge opts
56
55
 
57
56
  warn opts
58
57
  end
59
58
 
60
- def cve_2011_0447 new_version
59
+ def check_cve_2011_0447
60
+ @warned_cve_2011_0447 ||= false
61
+ return if @warned_cve_2011_0447
62
+
63
+ if version_between? "2.1.0", "2.3.10"
64
+ new_version = "2.3.11"
65
+ elsif version_between? "3.0.0", "3.0.3"
66
+ new_version = "3.0.4"
67
+ else
68
+ return
69
+ end
70
+
71
+ @warned_cve_2011_0447 = true # only warn once
72
+
61
73
  csrf_warning :warning_code => :CVE_2011_0447,
62
74
  :message => "CSRF protection is flawed in unpatched versions of Rails #{rails_version} (CVE-2011-0447). Upgrade to #{new_version} or apply patches as needed",
63
75
  :gem_info => gemfile_or_environment,