brakeman-lib 4.5.0 → 4.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +15 -0
  3. data/README.md +6 -6
  4. data/lib/brakeman.rb +7 -0
  5. data/lib/brakeman/app_tree.rb +34 -22
  6. data/lib/brakeman/checks.rb +7 -7
  7. data/lib/brakeman/checks/base_check.rb +9 -9
  8. data/lib/brakeman/checks/check_cross_site_scripting.rb +5 -0
  9. data/lib/brakeman/checks/check_default_routes.rb +5 -0
  10. data/lib/brakeman/checks/check_deserialize.rb +52 -0
  11. data/lib/brakeman/checks/check_dynamic_finders.rb +1 -1
  12. data/lib/brakeman/checks/check_force_ssl.rb +27 -0
  13. data/lib/brakeman/checks/check_json_parsing.rb +5 -0
  14. data/lib/brakeman/checks/check_link_to_href.rb +6 -1
  15. data/lib/brakeman/checks/check_mail_to.rb +1 -1
  16. data/lib/brakeman/checks/check_model_attr_accessible.rb +1 -1
  17. data/lib/brakeman/checks/check_model_attributes.rb +12 -50
  18. data/lib/brakeman/checks/check_model_serialize.rb +1 -1
  19. data/lib/brakeman/checks/check_nested_attributes_bypass.rb +3 -3
  20. data/lib/brakeman/checks/check_secrets.rb +1 -1
  21. data/lib/brakeman/checks/check_session_settings.rb +10 -10
  22. data/lib/brakeman/checks/check_simple_format.rb +5 -0
  23. data/lib/brakeman/checks/check_skip_before_filter.rb +1 -1
  24. data/lib/brakeman/checks/check_sql.rb +15 -17
  25. data/lib/brakeman/checks/check_validation_regex.rb +1 -1
  26. data/lib/brakeman/file_parser.rb +6 -8
  27. data/lib/brakeman/file_path.rb +71 -0
  28. data/lib/brakeman/options.rb +7 -0
  29. data/lib/brakeman/parsers/template_parser.rb +3 -3
  30. data/lib/brakeman/processor.rb +3 -4
  31. data/lib/brakeman/processors/alias_processor.rb +12 -6
  32. data/lib/brakeman/processors/base_processor.rb +8 -7
  33. data/lib/brakeman/processors/controller_alias_processor.rb +10 -7
  34. data/lib/brakeman/processors/controller_processor.rb +5 -9
  35. data/lib/brakeman/processors/haml_template_processor.rb +5 -0
  36. data/lib/brakeman/processors/lib/module_helper.rb +8 -8
  37. data/lib/brakeman/processors/lib/processor_helper.rb +3 -3
  38. data/lib/brakeman/processors/lib/rails2_config_processor.rb +3 -3
  39. data/lib/brakeman/processors/lib/rails2_route_processor.rb +2 -2
  40. data/lib/brakeman/processors/lib/rails3_config_processor.rb +3 -3
  41. data/lib/brakeman/processors/lib/rails3_route_processor.rb +2 -2
  42. data/lib/brakeman/processors/lib/render_helper.rb +2 -2
  43. data/lib/brakeman/processors/lib/render_path.rb +18 -1
  44. data/lib/brakeman/processors/library_processor.rb +5 -5
  45. data/lib/brakeman/processors/model_processor.rb +4 -5
  46. data/lib/brakeman/processors/output_processor.rb +5 -0
  47. data/lib/brakeman/processors/template_alias_processor.rb +4 -5
  48. data/lib/brakeman/processors/template_processor.rb +4 -4
  49. data/lib/brakeman/report.rb +3 -3
  50. data/lib/brakeman/report/ignore/config.rb +2 -3
  51. data/lib/brakeman/report/ignore/interactive.rb +2 -2
  52. data/lib/brakeman/report/pager.rb +1 -0
  53. data/lib/brakeman/report/report_base.rb +51 -6
  54. data/lib/brakeman/report/report_codeclimate.rb +3 -3
  55. data/lib/brakeman/report/report_hash.rb +1 -1
  56. data/lib/brakeman/report/report_html.rb +2 -2
  57. data/lib/brakeman/report/report_json.rb +1 -24
  58. data/lib/brakeman/report/report_table.rb +20 -4
  59. data/lib/brakeman/report/report_tabs.rb +1 -1
  60. data/lib/brakeman/report/report_text.rb +2 -2
  61. data/lib/brakeman/rescanner.rb +9 -12
  62. data/lib/brakeman/scanner.rb +19 -14
  63. data/lib/brakeman/tracker.rb +4 -4
  64. data/lib/brakeman/tracker/collection.rb +4 -3
  65. data/lib/brakeman/tracker/config.rb +6 -0
  66. data/lib/brakeman/util.rb +1 -147
  67. data/lib/brakeman/version.rb +1 -1
  68. data/lib/brakeman/warning.rb +23 -13
  69. data/lib/brakeman/warning_codes.rb +1 -0
  70. data/lib/ruby_parser/bm_sexp_processor.rb +1 -0
  71. metadata +20 -10
@@ -12,7 +12,7 @@ class Brakeman::Tracker
12
12
  attr_accessor :controllers, :constants, :templates, :models, :errors,
13
13
  :checks, :initializers, :config, :routes, :processor, :libs,
14
14
  :template_cache, :options, :filter_cache, :start_time, :end_time,
15
- :duration, :ignored_filter
15
+ :duration, :ignored_filter, :app_tree
16
16
 
17
17
  #Place holder when there should be a model, but it is not
18
18
  #clear what model it will be.
@@ -34,7 +34,7 @@ class Brakeman::Tracker
34
34
  #we can match models later without knowing precisely what
35
35
  #class they are.
36
36
  @models = {}
37
- @models[UNKNOWN_MODEL] = Brakeman::Model.new(UNKNOWN_MODEL, nil, nil, nil, self)
37
+ @models[UNKNOWN_MODEL] = Brakeman::Model.new(UNKNOWN_MODEL, nil, @app_tree.file_path("NOT_REAL.rb"), nil, self)
38
38
  @routes = {}
39
39
  @initializers = {}
40
40
  @errors = []
@@ -71,7 +71,7 @@ class Brakeman::Tracker
71
71
  #Run a set of checks on the current information. Results will be stored
72
72
  #in Tracker#checks.
73
73
  def run_checks
74
- @checks = Brakeman::Checks.run_checks(@app_tree, self)
74
+ @checks = Brakeman::Checks.run_checks(self)
75
75
 
76
76
  @end_time = Time.now
77
77
  @duration = @end_time - @start_time
@@ -172,7 +172,7 @@ class Brakeman::Tracker
172
172
 
173
173
  #Returns a Report with this Tracker's information
174
174
  def report
175
- Brakeman::Report.new(@app_tree, self)
175
+ Brakeman::Report.new(self)
176
176
  end
177
177
 
178
178
  def warnings
@@ -9,13 +9,14 @@ module Brakeman
9
9
  def initialize name, parent, file_name, src, tracker
10
10
  @name = name
11
11
  @parent = parent
12
- @file_name = file_name
13
- @files = [ file_name ]
14
- @src = { file_name => src }
12
+ @files = []
13
+ @src = {}
15
14
  @includes = []
16
15
  @methods = { :public => {}, :private => {}, :protected => {} }
17
16
  @options = {}
18
17
  @tracker = tracker
18
+
19
+ add_file file_name, src
19
20
  end
20
21
 
21
22
  def ancestor? parent, seen={}
@@ -97,6 +97,12 @@ module Brakeman
97
97
  tracker.options[:rails4] = true
98
98
  tracker.options[:rails5] = true
99
99
  Brakeman.notify "[Notice] Detected Rails 5 application"
100
+ elsif @rails_version.start_with? "6"
101
+ tracker.options[:rails3] = true
102
+ tracker.options[:rails4] = true
103
+ tracker.options[:rails5] = true
104
+ tracker.options[:rails6] = true
105
+ Brakeman.notify "[Notice] Detected Rails 6 application"
100
106
  end
101
107
  end
102
108
  end
@@ -346,158 +346,12 @@ module Brakeman::Util
346
346
  @tracker.config.rails_version
347
347
  end
348
348
 
349
- #Return file name related to given warning. Uses +warning.file+ if it exists
350
- def file_for warning, tracker = nil
351
- if tracker.nil?
352
- tracker = @tracker || self.tracker
353
- end
354
-
355
- if warning.file
356
- File.expand_path warning.file, tracker.app_path
357
- elsif warning.template and warning.template.file
358
- warning.template.file
359
- else
360
- case warning.warning_set
361
- when :controller
362
- file_by_name warning.controller, :controller, tracker
363
- when :template
364
- file_by_name warning.template.name, :template, tracker
365
- when :model
366
- file_by_name warning.model, :model, tracker
367
- when :warning
368
- file_by_name warning.class, nil, tracker
369
- else
370
- nil
371
- end
372
- end
373
- end
374
-
375
- #Attempt to determine path to context file based on the reported name
376
- #in the warning.
377
- #
378
- #For example,
379
- #
380
- # file_by_name FileController #=> "/rails/root/app/controllers/file_controller.rb
381
- def file_by_name name, type, tracker = nil
382
- return nil unless name
383
- string_name = name.to_s
384
- name = name.to_sym
385
-
386
- unless type
387
- if string_name =~ /Controller$/
388
- type = :controller
389
- elsif camelize(string_name) == string_name # This is not always true
390
- type = :model
391
- else
392
- type = :template
393
- end
394
- end
395
-
396
- path = tracker.app_path
397
-
398
- case type
399
- when :controller
400
- if tracker.controllers[name]
401
- path = tracker.controllers[name].file
402
- else
403
- path += "/app/controllers/#{underscore(string_name)}.rb"
404
- end
405
- when :model
406
- if tracker.models[name]
407
- path = tracker.models[name].file
408
- else
409
- path += "/app/models/#{underscore(string_name)}.rb"
410
- end
411
- when :template
412
- if tracker.templates[name] and tracker.templates[name].file
413
- path = tracker.templates[name].file
414
- elsif string_name.include? " "
415
- name = string_name.split[0].to_sym
416
- path = file_for tracker, name, :template
417
- else
418
- path = nil
419
- end
420
- end
421
-
422
- path
423
- end
424
-
425
- #Return array of lines surrounding the warning location from the original
426
- #file.
427
- def context_for app_tree, warning, tracker = nil
428
- file = file_for warning, tracker
429
- context = []
430
- return context unless warning.line and file and @app_tree.path_exists? file
431
-
432
- current_line = 0
433
- start_line = warning.line - 5
434
- end_line = warning.line + 5
435
-
436
- start_line = 1 if start_line < 0
437
-
438
- File.open file do |f|
439
- f.each_line do |line|
440
- current_line += 1
441
-
442
- next if line.strip == ""
443
-
444
- if current_line > end_line
445
- break
446
- end
447
-
448
- if current_line >= start_line
449
- context << [current_line, line]
450
- end
451
- end
452
- end
453
-
454
- context
455
- end
456
-
457
- def relative_path file
458
- pname = Pathname.new file
459
- if file and not file.empty? and pname.absolute?
460
- pname.relative_path_from(Pathname.new(@tracker.app_path)).to_s
461
- else
462
- file
463
- end
464
- end
465
-
466
349
  #Convert path/filename to view name
467
350
  #
468
351
  # views/test/something.html.erb -> test/something
469
352
  def template_path_to_name path
470
- names = path.split("/")
353
+ names = path.relative.split("/")
471
354
  names.last.gsub!(/(\.(html|js)\..*|\.(rhtml|haml|erb|slim))$/, '')
472
355
  names[(names.index("views") + 1)..-1].join("/").to_sym
473
356
  end
474
-
475
- def github_url file, line=nil
476
- if repo_url = @tracker.options[:github_url] and file and not file.empty? and file.start_with? '/'
477
- url = "#{repo_url}/#{relative_path(file)}"
478
- url << "#L#{line}" if line
479
- else
480
- nil
481
- end
482
- end
483
-
484
- def truncate_table str
485
- @terminal_width ||= if @tracker.options[:table_width]
486
- @tracker.options[:table_width]
487
- elsif $stdin && $stdin.tty?
488
- Brakeman.load_brakeman_dependency 'highline'
489
- ::HighLine.new.terminal_size[0]
490
- else
491
- 80
492
- end
493
- lines = str.lines
494
-
495
- lines.map do |line|
496
- if line.chomp.length > @terminal_width
497
- line[0..(@terminal_width - 3)] + ">>\n"
498
- else
499
- line
500
- end
501
- end.join
502
- end
503
357
  end
@@ -1,3 +1,3 @@
1
1
  module Brakeman
2
- Version = "4.5.0"
2
+ Version = "4.5.1"
3
3
  end
@@ -9,7 +9,7 @@ class Brakeman::Warning
9
9
  :line, :method, :model, :template, :user_input, :user_input_type,
10
10
  :warning_code, :warning_set, :warning_type
11
11
 
12
- attr_accessor :code, :context, :file, :message, :relative_path
12
+ attr_accessor :code, :context, :file, :message
13
13
 
14
14
  TEXT_CONFIDENCE = {
15
15
  0 => "High",
@@ -34,11 +34,11 @@ class Brakeman::Warning
34
34
  :file => :@file,
35
35
  :gem_info => :@gem_info,
36
36
  :line => :@line,
37
+ :link => :@link,
37
38
  :link_path => :@link_path,
38
39
  :message => :@message,
39
40
  :method => :@method,
40
41
  :model => :@model,
41
- :relative_path => :@relative_path,
42
42
  :template => :@template,
43
43
  :user_input => :@user_input,
44
44
  :warning_set => :@warning_set,
@@ -100,9 +100,11 @@ class Brakeman::Warning
100
100
  unless @warning_set
101
101
  if self.model
102
102
  @warning_set = :model
103
+ @file ||= self.model.file
103
104
  elsif self.template
104
105
  @warning_set = :template
105
106
  @called_from = self.template.render_path
107
+ @file ||= self.template.file
106
108
  elsif self.controller
107
109
  @warning_set = :controller
108
110
  else
@@ -112,6 +114,8 @@ class Brakeman::Warning
112
114
 
113
115
  if options[:warning_code]
114
116
  @warning_code = Brakeman::WarningCodes.code options[:warning_code]
117
+ else
118
+ @warning_code = nil
115
119
  end
116
120
 
117
121
  Brakeman.debug("Warning created without warning code: #{options[:warning_code]}") unless @warning_code
@@ -221,7 +225,7 @@ class Brakeman::Warning
221
225
  when :template
222
226
  @row["Template"] = self.view_name.to_s
223
227
  when :model
224
- @row["Model"] = self.model.to_s
228
+ @row["Model"] = self.model.name.to_s
225
229
  when :controller
226
230
  @row["Controller"] = self.controller.to_s
227
231
  when :warning
@@ -235,7 +239,7 @@ class Brakeman::Warning
235
239
  def to_s
236
240
  output = "(#{TEXT_CONFIDENCE[self.confidence]}) #{self.warning_type} - #{self.message}"
237
241
  output << " near line #{self.line}" if self.line
238
- output << " in #{self.file}" if self.file
242
+ output << " in #{self.file.relative}" if self.file
239
243
  output << ": #{self.format_code}" if self.code
240
244
 
241
245
  output
@@ -247,37 +251,43 @@ class Brakeman::Warning
247
251
  warning_code_string = sprintf("%03d", @warning_code)
248
252
  code_string = @code.inspect
249
253
 
250
- Digest::SHA2.new(256).update("#{warning_code_string}#{code_string}#{location_string}#{@relative_path}#{self.confidence}").to_s
254
+ Digest::SHA2.new(256).update("#{warning_code_string}#{code_string}#{location_string}#{self.file.relative}#{self.confidence}").to_s
251
255
  end
252
256
 
253
257
  def location include_renderer = true
254
258
  case @warning_set
255
259
  when :template
256
- location = { :type => :template, :template => self.view_name(include_renderer) }
260
+ { :type => :template, :template => self.view_name(include_renderer) }
257
261
  when :model
258
- location = { :type => :model, :model => self.model }
262
+ { :type => :model, :model => self.model.name }
259
263
  when :controller
260
- location = { :type => :controller, :controller => self.controller }
264
+ { :type => :controller, :controller => self.controller }
261
265
  when :warning
262
266
  if self.class
263
- location = { :type => :method, :class => self.class, :method => self.method }
267
+ { :type => :method, :class => self.class, :method => self.method }
264
268
  else
265
- location = nil
269
+ nil
266
270
  end
267
271
  end
268
272
  end
269
273
 
270
- def to_hash
274
+ def to_hash absolute_paths: true
275
+ if self.called_from and not absolute_paths
276
+ render_path = self.called_from.with_relative_paths
277
+ else
278
+ render_path = self.called_from
279
+ end
280
+
271
281
  { :warning_type => self.warning_type,
272
282
  :warning_code => @warning_code,
273
283
  :fingerprint => self.fingerprint,
274
284
  :check_name => self.check.gsub(/^Brakeman::Check/, ''),
275
285
  :message => self.message.to_s,
276
- :file => self.file,
286
+ :file => (absolute_paths ? self.file.absolute : self.file.relative),
277
287
  :line => self.line,
278
288
  :link => self.link,
279
289
  :code => (@code && self.format_code(false)),
280
- :render_path => self.called_from,
290
+ :render_path => render_path,
281
291
  :location => self.location(false),
282
292
  :user_input => (@user_input && self.format_user_input(false)),
283
293
  :confidence => TEXT_CONFIDENCE[self.confidence]
@@ -110,6 +110,7 @@ module Brakeman::WarningCodes
110
110
  :CVE_2018_8048 => 106,
111
111
  :CVE_2018_3741 => 107,
112
112
  :CVE_2018_3760 => 108,
113
+ :force_ssl_disabled => 109,
113
114
  }
114
115
 
115
116
  def self.code name
@@ -45,6 +45,7 @@ class Brakeman::SexpProcessor
45
45
  @expected = Sexp
46
46
  @processors = self.class.processors
47
47
  @context = []
48
+ @current_class = @current_module = @current_method = @visibility = nil
48
49
 
49
50
  if @processors.empty?
50
51
  public_methods.each do |name|
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brakeman-lib
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.5.0
4
+ version: 4.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Collins
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain:
11
11
  - brakeman-public_cert.pem
12
- date: 2019-03-16 00:00:00.000000000 Z
12
+ date: 2019-05-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: minitest
@@ -39,6 +39,20 @@ dependencies:
39
39
  - - ">="
40
40
  - !ruby/object:Gem::Version
41
41
  version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: simplecov
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
42
56
  - !ruby/object:Gem::Dependency
43
57
  name: ruby_parser
44
58
  requirement: !ruby/object:Gem::Requirement
@@ -127,20 +141,14 @@ dependencies:
127
141
  name: highline
128
142
  requirement: !ruby/object:Gem::Requirement
129
143
  requirements:
130
- - - ">="
131
- - !ruby/object:Gem::Version
132
- version: 1.6.20
133
- - - "<"
144
+ - - "~>"
134
145
  - !ruby/object:Gem::Version
135
146
  version: '2.0'
136
147
  type: :runtime
137
148
  prerelease: false
138
149
  version_requirements: !ruby/object:Gem::Requirement
139
150
  requirements:
140
- - - ">="
141
- - !ruby/object:Gem::Version
142
- version: 1.6.20
143
- - - "<"
151
+ - - "~>"
144
152
  - !ruby/object:Gem::Version
145
153
  version: '2.0'
146
154
  - !ruby/object:Gem::Dependency
@@ -232,6 +240,7 @@ files:
232
240
  - lib/brakeman/checks/check_file_access.rb
233
241
  - lib/brakeman/checks/check_file_disclosure.rb
234
242
  - lib/brakeman/checks/check_filter_skipping.rb
243
+ - lib/brakeman/checks/check_force_ssl.rb
235
244
  - lib/brakeman/checks/check_forgery_setting.rb
236
245
  - lib/brakeman/checks/check_header_dos.rb
237
246
  - lib/brakeman/checks/check_i18n_xss.rb
@@ -289,6 +298,7 @@ files:
289
298
  - lib/brakeman/commandline.rb
290
299
  - lib/brakeman/differ.rb
291
300
  - lib/brakeman/file_parser.rb
301
+ - lib/brakeman/file_path.rb
292
302
  - lib/brakeman/format/style.css
293
303
  - lib/brakeman/messages.rb
294
304
  - lib/brakeman/options.rb