brakeman 5.0.1 → 5.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +41 -0
  3. data/bundle/load.rb +3 -2
  4. data/bundle/ruby/2.7.0/gems/parallel-1.20.1/MIT-LICENSE.txt +20 -0
  5. data/bundle/ruby/2.7.0/gems/parallel-1.20.1/lib/parallel.rb +523 -0
  6. data/bundle/ruby/2.7.0/gems/parallel-1.20.1/lib/parallel/processor_count.rb +42 -0
  7. data/bundle/ruby/2.7.0/gems/parallel-1.20.1/lib/parallel/version.rb +3 -0
  8. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.1 → ruby_parser-3.16.0}/History.rdoc +19 -0
  9. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.1 → ruby_parser-3.16.0}/Manifest.txt +2 -0
  10. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.1 → ruby_parser-3.16.0}/README.rdoc +0 -0
  11. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.1 → ruby_parser-3.16.0}/compare/normalize.rb +2 -2
  12. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.1 → ruby_parser-3.16.0}/debugging.md +0 -0
  13. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.1 → ruby_parser-3.16.0}/lib/rp_extensions.rb +0 -0
  14. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.1 → ruby_parser-3.16.0}/lib/rp_stringscanner.rb +0 -0
  15. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.1 → ruby_parser-3.16.0}/lib/ruby20_parser.rb +0 -0
  16. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.1 → ruby_parser-3.16.0}/lib/ruby20_parser.y +0 -0
  17. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.1 → ruby_parser-3.16.0}/lib/ruby21_parser.rb +0 -0
  18. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.1 → ruby_parser-3.16.0}/lib/ruby21_parser.y +0 -0
  19. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.1 → ruby_parser-3.16.0}/lib/ruby22_parser.rb +0 -0
  20. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.1 → ruby_parser-3.16.0}/lib/ruby22_parser.y +0 -0
  21. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.1 → ruby_parser-3.16.0}/lib/ruby23_parser.rb +0 -0
  22. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.1 → ruby_parser-3.16.0}/lib/ruby23_parser.y +0 -0
  23. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.1 → ruby_parser-3.16.0}/lib/ruby24_parser.rb +0 -0
  24. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.1 → ruby_parser-3.16.0}/lib/ruby24_parser.y +0 -0
  25. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.1 → ruby_parser-3.16.0}/lib/ruby25_parser.rb +0 -0
  26. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.1 → ruby_parser-3.16.0}/lib/ruby25_parser.y +0 -0
  27. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.1 → ruby_parser-3.16.0}/lib/ruby26_parser.rb +0 -0
  28. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.1 → ruby_parser-3.16.0}/lib/ruby26_parser.y +0 -0
  29. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.1 → ruby_parser-3.16.0}/lib/ruby27_parser.rb +0 -0
  30. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.1 → ruby_parser-3.16.0}/lib/ruby27_parser.y +0 -0
  31. data/bundle/ruby/2.7.0/gems/ruby_parser-3.16.0/lib/ruby30_parser.rb +7358 -0
  32. data/bundle/ruby/2.7.0/gems/ruby_parser-3.16.0/lib/ruby30_parser.y +2703 -0
  33. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.1 → ruby_parser-3.16.0}/lib/ruby_lexer.rb +0 -0
  34. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.1 → ruby_parser-3.16.0}/lib/ruby_lexer.rex +0 -0
  35. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.1 → ruby_parser-3.16.0}/lib/ruby_lexer.rex.rb +0 -0
  36. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.1 → ruby_parser-3.16.0}/lib/ruby_parser.rb +2 -0
  37. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.1 → ruby_parser-3.16.0}/lib/ruby_parser.yy +2 -0
  38. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.1 → ruby_parser-3.16.0}/lib/ruby_parser_extras.rb +2 -2
  39. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.1 → ruby_parser-3.16.0}/tools/munge.rb +0 -0
  40. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.15.1 → ruby_parser-3.16.0}/tools/ripper.rb +0 -0
  41. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.15.2 → sexp_processor-4.15.3}/History.rdoc +6 -0
  42. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.15.2 → sexp_processor-4.15.3}/Manifest.txt +0 -0
  43. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.15.2 → sexp_processor-4.15.3}/README.rdoc +0 -0
  44. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.15.2 → sexp_processor-4.15.3}/lib/composite_sexp_processor.rb +0 -0
  45. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.15.2 → sexp_processor-4.15.3}/lib/pt_testcase.rb +2 -2
  46. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.15.2 → sexp_processor-4.15.3}/lib/sexp.rb +0 -0
  47. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.15.2 → sexp_processor-4.15.3}/lib/sexp_matcher.rb +0 -0
  48. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.15.2 → sexp_processor-4.15.3}/lib/sexp_processor.rb +1 -1
  49. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.15.2 → sexp_processor-4.15.3}/lib/strict_sexp.rb +0 -0
  50. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.15.2 → sexp_processor-4.15.3}/lib/unique.rb +0 -0
  51. data/lib/brakeman.rb +6 -0
  52. data/lib/brakeman/checks/check_detailed_exceptions.rb +1 -1
  53. data/lib/brakeman/checks/check_evaluation.rb +1 -1
  54. data/lib/brakeman/checks/check_execute.rb +10 -0
  55. data/lib/brakeman/checks/check_render.rb +15 -1
  56. data/lib/brakeman/checks/check_sanitize_methods.rb +2 -1
  57. data/lib/brakeman/checks/check_sql.rb +58 -8
  58. data/lib/brakeman/checks/check_verb_confusion.rb +1 -1
  59. data/lib/brakeman/file_parser.rb +45 -15
  60. data/lib/brakeman/options.rb +7 -2
  61. data/lib/brakeman/processors/alias_processor.rb +85 -9
  62. data/lib/brakeman/processors/controller_alias_processor.rb +6 -43
  63. data/lib/brakeman/processors/lib/call_conversion_helper.rb +10 -6
  64. data/lib/brakeman/processors/library_processor.rb +9 -0
  65. data/lib/brakeman/processors/model_processor.rb +31 -0
  66. data/lib/brakeman/report.rb +4 -1
  67. data/lib/brakeman/report/ignore/interactive.rb +1 -1
  68. data/lib/brakeman/report/report_github.rb +31 -0
  69. data/lib/brakeman/report/report_sarif.rb +21 -2
  70. data/lib/brakeman/rescanner.rb +1 -1
  71. data/lib/brakeman/scanner.rb +4 -1
  72. data/lib/brakeman/tracker.rb +33 -4
  73. data/lib/brakeman/tracker/collection.rb +57 -7
  74. data/lib/brakeman/tracker/method_info.rb +70 -0
  75. data/lib/brakeman/util.rb +34 -18
  76. data/lib/brakeman/version.rb +1 -1
  77. data/lib/ruby_parser/bm_sexp.rb +14 -0
  78. metadata +51 -43
@@ -79,10 +79,12 @@ require "ruby24_parser"
79
79
  require "ruby25_parser"
80
80
  require "ruby26_parser"
81
81
  require "ruby27_parser"
82
+ require "ruby30_parser"
82
83
 
83
84
  class RubyParser # HACK
84
85
  VERSIONS.clear # also a HACK caused by racc namespace issues
85
86
 
87
+ class V30 < ::Ruby30Parser; end
86
88
  class V27 < ::Ruby27Parser; end
87
89
  class V26 < ::Ruby26Parser; end
88
90
  class V25 < ::Ruby25Parser; end
@@ -16,6 +16,8 @@ class Ruby25Parser
16
16
  class Ruby26Parser
17
17
  #elif V == 27
18
18
  class Ruby27Parser
19
+ #elif V == 30
20
+ class Ruby30Parser
19
21
  #else
20
22
  fail "version not specified or supported on code generation"
21
23
  #endif
@@ -29,7 +29,7 @@ class Sexp
29
29
  end
30
30
 
31
31
  module RubyParserStuff
32
- VERSION = "3.15.1"
32
+ VERSION = "3.16.0"
33
33
 
34
34
  attr_accessor :lexer, :in_def, :in_single, :file
35
35
  attr_accessor :in_kwarg
@@ -115,7 +115,7 @@ module RubyParserStuff
115
115
  def initialize(options = {})
116
116
  super()
117
117
 
118
- v = self.class.name[/2\d/]
118
+ v = self.class.name[/[23]\d/]
119
119
  raise "Bad Class name #{self.class}" unless v
120
120
 
121
121
  self.lexer = RubyLexer.new v && v.to_i
@@ -1,3 +1,9 @@
1
+ === 4.15.3 / 2021-05-15
2
+
3
+ * 1 minor enhancement:
4
+
5
+ * Added 3.0 to pt_testcase.rb
6
+
1
7
  === 4.15.2 / 2021-01-10
2
8
 
3
9
  * 1 bug fix:
@@ -77,7 +77,7 @@ class ParseTreeTestCase < Minitest::Test
77
77
  end
78
78
 
79
79
  def self.add_19tests name, hash
80
- add_tests "#{name}__19_20_21_22_23_24_25_26_27", hash # HACK?
80
+ add_tests "#{name}__19_20_21_22_23_24_25_26_27_30", hash # HACK?
81
81
  end
82
82
 
83
83
  def self.add_19edgecases ruby, sexp, cases
@@ -102,7 +102,7 @@ class ParseTreeTestCase < Minitest::Test
102
102
  testcases[verbose][klass] = testcases[nonverbose][klass]
103
103
  end
104
104
 
105
- VER_RE = "(1[89]|2[01234567])"
105
+ VER_RE = "(1[89]|2[01234567]|3[0])"
106
106
 
107
107
  def self.generate_test klass, node, data, input_name, output_name
108
108
  klass.send :define_method, "test_#{node}" do
@@ -34,7 +34,7 @@ require "sexp"
34
34
  class SexpProcessor
35
35
 
36
36
  # duh
37
- VERSION = "4.15.2"
37
+ VERSION = "4.15.3"
38
38
 
39
39
  ##
40
40
  # Automatically shifts off the Sexp type before handing the
data/lib/brakeman.rb CHANGED
@@ -65,6 +65,7 @@ module Brakeman
65
65
  # * :report_routes - show found routes on controllers (default: false)
66
66
  # * :run_checks - array of checks to run (run all if not specified)
67
67
  # * :safe_methods - array of methods to consider safe
68
+ # * :sql_safe_methods - array of sql sanitization methods to consider safe
68
69
  # * :skip_libs - do not process lib/ directory (default: false)
69
70
  # * :skip_vendor - do not process vendor/ directory (default: true)
70
71
  # * :skip_checks - checks not to run (run all if not specified)
@@ -198,6 +199,7 @@ module Brakeman
198
199
  :relative_path => false,
199
200
  :report_progress => true,
200
201
  :safe_methods => Set.new,
202
+ :sql_safe_methods => Set.new,
201
203
  :skip_checks => Set.new,
202
204
  :skip_vendor => true,
203
205
  }
@@ -250,6 +252,8 @@ module Brakeman
250
252
  [:to_sarif]
251
253
  when :sonar, :to_sonar
252
254
  [:to_sonar]
255
+ when :github, :to_github
256
+ [:to_github]
253
257
  else
254
258
  [:to_text]
255
259
  end
@@ -283,6 +287,8 @@ module Brakeman
283
287
  :to_sarif
284
288
  when /\.sonar$/i
285
289
  :to_sonar
290
+ when /\.github$/i
291
+ :to_github
286
292
  else
287
293
  :to_text
288
294
  end
@@ -26,7 +26,7 @@ class Brakeman::CheckDetailedExceptions < Brakeman::BaseCheck
26
26
  def check_detailed_exceptions
27
27
  tracker.controllers.each do |_name, controller|
28
28
  controller.methods_public.each do |method_name, definition|
29
- src = definition[:src]
29
+ src = definition.src
30
30
  body = src.body.last
31
31
  next unless body
32
32
 
@@ -10,7 +10,7 @@ class Brakeman::CheckEvaluation < Brakeman::BaseCheck
10
10
  #Process calls
11
11
  def run_check
12
12
  Brakeman.debug "Finding eval-like calls"
13
- calls = tracker.find_call :method => [:eval, :instance_eval, :class_eval, :module_eval]
13
+ calls = tracker.find_call methods: [:eval, :instance_eval, :class_eval, :module_eval], nested: true
14
14
 
15
15
  Brakeman.debug "Processing eval-like calls"
16
16
  calls.each do |call|
@@ -87,6 +87,16 @@ class Brakeman::CheckExecute < Brakeman::BaseCheck
87
87
  dangerous_interp?(first_arg) ||
88
88
  dangerous_string_building?(first_arg)
89
89
  end
90
+ when :capture2, :capture2e, :capture3
91
+ # Open3 capture methods can take a :stdin_data argument which is used as the
92
+ # the input to the called command so it is not succeptable to command injection.
93
+ # As such if the last argument is a hash (and therefore execution options) it
94
+ # should be ignored
95
+
96
+ args.pop if hash?(args.last) && args.length > 2
97
+ failure = include_user_input?(args) ||
98
+ dangerous_interp?(args) ||
99
+ dangerous_string_building?(args)
90
100
  else
91
101
  failure = include_user_input?(args) ||
92
102
  dangerous_interp?(args) ||
@@ -33,6 +33,7 @@ class Brakeman::CheckRender < Brakeman::BaseCheck
33
33
  view = result[:call][2]
34
34
 
35
35
  if sexp? view and original? result
36
+ return if renderable?(view)
36
37
 
37
38
  if input = has_immediate_user_input?(view)
38
39
  if string_interp? view
@@ -94,4 +95,17 @@ class Brakeman::CheckRender < Brakeman::BaseCheck
94
95
  end
95
96
  end
96
97
  end
97
- end
98
+
99
+ def renderable? exp
100
+ return false unless call?(exp) and constant?(exp.target)
101
+
102
+ target_class_name = class_name(exp.target)
103
+ known_renderable_class?(target_class_name) or tracker.find_method(:render_in, target_class_name)
104
+ end
105
+
106
+ def known_renderable_class? class_name
107
+ klass = tracker.find_class(class_name)
108
+ return false if klass.nil?
109
+ klass.ancestor? :"ViewComponent::Base"
110
+ end
111
+ end
@@ -90,7 +90,8 @@ class Brakeman::CheckSanitizeMethods < Brakeman::BaseCheck
90
90
  def loofah_vulnerable_cve_2018_8048?
91
91
  loofah_version = tracker.config.gem_version(:loofah)
92
92
 
93
- loofah_version and loofah_version < "2.2.1"
93
+ # 2.2.1 is fix version
94
+ loofah_version and version_between?("0.0.0", "2.2.0", loofah_version)
94
95
  end
95
96
 
96
97
  def warn_sanitizer_cve cve, link, upgrade_version
@@ -22,7 +22,19 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
22
22
  :find_by_sql, :maximum, :minimum, :pluck, :sum, :update_all]
23
23
  @sql_targets.concat [:from, :group, :having, :joins, :lock, :order, :reorder, :where] if tracker.options[:rails3]
24
24
  @sql_targets.concat [:find_by, :find_by!, :find_or_create_by, :find_or_create_by!, :find_or_initialize_by, :not] if tracker.options[:rails4]
25
- @sql_targets << :delete_by << :destroy_by if tracker.options[:rails6]
25
+
26
+ if tracker.options[:rails6]
27
+ @sql_targets.concat [:delete_by, :destroy_by, :rewhere, :reselect]
28
+
29
+ @sql_targets.delete :delete_all
30
+ @sql_targets.delete :destroy_all
31
+ end
32
+
33
+ if version_between?("6.1.0", "9.9.9")
34
+ @sql_targets.delete :order
35
+ @sql_targets.delete :reorder
36
+ @sql_targets.delete :pluck
37
+ end
26
38
 
27
39
  if version_between?("2.0.0", "3.9.9") or tracker.config.rails_version.nil?
28
40
  @sql_targets << :first << :last << :all
@@ -185,7 +197,7 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
185
197
  else
186
198
  check_find_arguments call.last_arg
187
199
  end
188
- when :where, :having, :find_by, :find_by!, :find_or_create_by, :find_or_create_by!, :find_or_initialize_by,:not, :delete_by, :destroy_by
200
+ when :where, :rewhere, :having, :find_by, :find_by!, :find_or_create_by, :find_or_create_by!, :find_or_initialize_by,:not, :delete_by, :destroy_by
189
201
  check_query_arguments call.arglist
190
202
  when :order, :group, :reorder
191
203
  check_order_arguments call.arglist
@@ -199,7 +211,7 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
199
211
  unsafe_sql? call.first_arg
200
212
  when :sql
201
213
  unsafe_sql? call.first_arg
202
- when :update_all, :select
214
+ when :update_all, :select, :reselect
203
215
  check_update_all_arguments call.args
204
216
  when *@connection_calls
205
217
  check_by_sql_arguments call.first_arg
@@ -572,13 +584,17 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
572
584
  end
573
585
 
574
586
  IGNORE_METHODS_IN_SQL = Set[:id, :merge_conditions, :table_name, :quoted_table_name,
575
- :quoted_primary_key, :to_i, :to_f, :sanitize_sql, :sanitize_sql_array,
587
+ :quoted_primary_key, :to_i, :to_f, :sanitize_sql, :sanitize_sql_array, :sanitize_sql_like,
576
588
  :sanitize_sql_for_assignment, :sanitize_sql_for_conditions, :sanitize_sql_hash,
577
589
  :sanitize_sql_hash_for_assignment, :sanitize_sql_hash_for_conditions,
578
590
  :to_sql, :sanitize, :primary_key, :table_name_prefix, :table_name_suffix,
579
591
  :where_values_hash, :foreign_key, :uuid
580
592
  ]
581
593
 
594
+ def ignore_methods_in_sql
595
+ @ignore_methods_in_sql ||= IGNORE_METHODS_IN_SQL + (tracker.options[:sql_safe_methods] || [])
596
+ end
597
+
582
598
  def safe_value? exp
583
599
  return true unless sexp? exp
584
600
 
@@ -589,10 +605,7 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
589
605
  if exp.method == :to_s or exp.method == :to_sym
590
606
  safe_value? exp.target
591
607
  else
592
- IGNORE_METHODS_IN_SQL.include? exp.method or
593
- quote_call? exp or
594
- arel? exp or
595
- exp.method.to_s.end_with? "_id"
608
+ ignore_call? exp
596
609
  end
597
610
  when :if
598
611
  safe_value? exp.then_clause and safe_value? exp.else_clause
@@ -607,6 +620,17 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
607
620
  end
608
621
  end
609
622
 
623
+ def ignore_call? exp
624
+ return unless call? exp
625
+
626
+ ignore_methods_in_sql.include? exp.method or
627
+ quote_call? exp or
628
+ arel? exp or
629
+ exp.method.to_s.end_with? "_id" or
630
+ number_target? exp or
631
+ date_target? exp
632
+ end
633
+
610
634
  QUOTE_METHODS = [:quote, :quote_column_name, :quoted_date, :quote_string, :quote_table_name]
611
635
 
612
636
  def quote_call? exp
@@ -695,4 +719,30 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
695
719
  active_record_models.include? klass
696
720
  end
697
721
  end
722
+
723
+ def number_target? exp
724
+ return unless call? exp
725
+
726
+ if number? exp.target
727
+ true
728
+ elsif call? exp.target
729
+ number_target? exp.target
730
+ else
731
+ false
732
+ end
733
+ end
734
+
735
+ DATE_CLASS = s(:const, :Date)
736
+
737
+ def date_target? exp
738
+ return unless call? exp
739
+
740
+ if exp.target == DATE_CLASS
741
+ true
742
+ elsif call? exp.target
743
+ date_target? exp.target
744
+ else
745
+ false
746
+ end
747
+ end
698
748
  end
@@ -32,7 +32,7 @@ class Brakeman::CheckVerbConfusion < Brakeman::BaseCheck
32
32
  return
33
33
  end
34
34
 
35
- process method[:src]
35
+ process method.src
36
36
  end
37
37
 
38
38
  def process_if exp
@@ -1,3 +1,5 @@
1
+ require 'parallel'
2
+
1
3
  module Brakeman
2
4
  ASTFile = Struct.new(:path, :ast)
3
5
 
@@ -5,29 +7,62 @@ module Brakeman
5
7
  class FileParser
6
8
  attr_reader :file_list, :errors
7
9
 
8
- def initialize app_tree, timeout
10
+ def initialize app_tree, timeout, parallel = true
9
11
  @app_tree = app_tree
10
12
  @timeout = timeout
11
13
  @file_list = []
12
14
  @errors = []
15
+ @parallel = parallel
13
16
  end
14
17
 
15
18
  def parse_files list
16
- read_files list do |path, contents|
17
- if ast = parse_ruby(contents, path.relative)
18
- ASTFile.new(path, ast)
19
+ if @parallel
20
+ parallel_options = {}
21
+ else
22
+ # Disable parallelism
23
+ parallel_options = { in_threads: 0 }
24
+ end
25
+
26
+ # Parse the files in parallel.
27
+ # By default, the parsing will be in separate processes.
28
+ # So we map the result to ASTFiles and/or Exceptions
29
+ # then partition them into ASTFiles and Exceptions
30
+ # and add the Exceptions to @errors
31
+ #
32
+ # Basically just a funky way to deal with two possible
33
+ # return types that are returned from isolated processes.
34
+ #
35
+ # Note this method no longer uses read_files
36
+ @file_list, new_errors = Parallel.map(list, parallel_options) do |file_name|
37
+ file_path = @app_tree.file_path(file_name)
38
+ contents = file_path.read
39
+
40
+ begin
41
+ if ast = parse_ruby(contents, file_path.relative)
42
+ ASTFile.new(file_name, ast)
43
+ end
44
+ rescue Exception => e
45
+ e
19
46
  end
47
+ end.compact.partition do |result|
48
+ result.is_a? ASTFile
20
49
  end
50
+
51
+ errors.concat new_errors
21
52
  end
22
53
 
23
54
  def read_files list
24
55
  list.each do |path|
25
56
  file = @app_tree.file_path(path)
26
57
 
27
- result = yield file, file.read
58
+ begin
59
+ result = yield file, file.read
28
60
 
29
- if result
30
- @file_list << result
61
+ if result
62
+ @file_list << result
63
+ end
64
+ rescue Exception => e
65
+ @errors << e
31
66
  end
32
67
  end
33
68
  end
@@ -42,17 +77,12 @@ module Brakeman
42
77
  Brakeman.debug "Parsing #{path}"
43
78
  RubyParser.new.parse input, path, @timeout
44
79
  rescue Racc::ParseError => e
45
- error e.exception(e.message + "\nCould not parse #{path}")
80
+ raise e.exception(e.message + "\nCould not parse #{path}")
46
81
  rescue Timeout::Error => e
47
- error Exception.new("Parsing #{path} took too long (> #{@timeout} seconds). Try increasing the limit with --parser-timeout")
82
+ raise Exception.new("Parsing #{path} took too long (> #{@timeout} seconds). Try increasing the limit with --parser-timeout")
48
83
  rescue => e
49
- error e.exception(e.message + "\nWhile processing #{path}")
84
+ raise e.exception(e.message + "\nWhile processing #{path}")
50
85
  end
51
86
  end
52
-
53
- def error exception
54
- @errors << exception
55
- nil
56
- end
57
87
  end
58
88
  end
@@ -39,7 +39,7 @@ module Brakeman::Options
39
39
  OptionParser.new do |opts|
40
40
  opts.banner = "Usage: brakeman [options] rails/root/path"
41
41
 
42
- opts.on "-n", "--no-threads", "Run checks sequentially" do
42
+ opts.on "-n", "--no-threads", "Run checks and file parsing sequentially" do
43
43
  options[:parallel_checks] = false
44
44
  end
45
45
 
@@ -151,6 +151,11 @@ module Brakeman::Options
151
151
  options[:safe_methods].merge methods.map {|e| e.to_sym }
152
152
  end
153
153
 
154
+ opts.on "--sql-safe-methods meth1,meth2,etc", Array, "Do not warn of SQL if the input is wrapped in a safe method" do |methods|
155
+ options[:sql_safe_methods] ||= Set.new
156
+ options[:sql_safe_methods].merge methods.map {|e| e.to_sym }
157
+ end
158
+
154
159
  opts.on "--url-safe-methods method1,method2,etc", Array, "Do not warn of XSS if the link_to href parameter is wrapped in a safe method" do |methods|
155
160
  options[:url_safe_methods] ||= Set.new
156
161
  options[:url_safe_methods].merge methods.map {|e| e.to_sym }
@@ -233,7 +238,7 @@ module Brakeman::Options
233
238
 
234
239
  opts.on "-f",
235
240
  "--format TYPE",
236
- [:pdf, :text, :html, :csv, :tabs, :json, :markdown, :codeclimate, :cc, :plain, :table, :junit, :sarif, :sonar],
241
+ [:pdf, :text, :html, :csv, :tabs, :json, :markdown, :codeclimate, :cc, :plain, :table, :junit, :sarif, :sonar, :github],
237
242
  "Specify output formats. Default is text" do |type|
238
243
 
239
244
  type = "s" if type == :text