brakeman-lib 5.0.4 → 5.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +49 -1
  3. data/README.md +1 -1
  4. data/lib/brakeman/app_tree.rb +1 -1
  5. data/lib/brakeman/checks/base_check.rb +10 -0
  6. data/lib/brakeman/checks/check_detailed_exceptions.rb +1 -1
  7. data/lib/brakeman/checks/check_eol_rails.rb +23 -0
  8. data/lib/brakeman/checks/check_eol_ruby.rb +26 -0
  9. data/lib/brakeman/checks/check_evaluation.rb +1 -1
  10. data/lib/brakeman/checks/check_execute.rb +10 -0
  11. data/lib/brakeman/checks/check_json_parsing.rb +1 -1
  12. data/lib/brakeman/checks/check_render.rb +15 -1
  13. data/lib/brakeman/checks/check_sql.rb +58 -7
  14. data/lib/brakeman/checks/check_symbol_dos.rb +1 -1
  15. data/lib/brakeman/checks/check_verb_confusion.rb +1 -1
  16. data/lib/brakeman/checks/eol_check.rb +47 -0
  17. data/lib/brakeman/file_parser.rb +45 -15
  18. data/lib/brakeman/options.rb +15 -2
  19. data/lib/brakeman/processors/alias_processor.rb +91 -9
  20. data/lib/brakeman/processors/controller_alias_processor.rb +6 -43
  21. data/lib/brakeman/processors/gem_processor.rb +3 -0
  22. data/lib/brakeman/processors/haml_template_processor.rb +9 -0
  23. data/lib/brakeman/processors/lib/call_conversion_helper.rb +12 -6
  24. data/lib/brakeman/processors/lib/rails3_route_processor.rb +2 -0
  25. data/lib/brakeman/processors/library_processor.rb +9 -0
  26. data/lib/brakeman/processors/model_processor.rb +32 -0
  27. data/lib/brakeman/report/ignore/config.rb +1 -1
  28. data/lib/brakeman/report/ignore/interactive.rb +1 -1
  29. data/lib/brakeman/report/report_csv.rb +1 -1
  30. data/lib/brakeman/report/report_github.rb +31 -0
  31. data/lib/brakeman/report/report_sarif.rb +22 -3
  32. data/lib/brakeman/report/report_text.rb +1 -1
  33. data/lib/brakeman/report.rb +4 -1
  34. data/lib/brakeman/rescanner.rb +1 -1
  35. data/lib/brakeman/scanner.rb +19 -14
  36. data/lib/brakeman/tracker/collection.rb +57 -7
  37. data/lib/brakeman/tracker/config.rb +8 -1
  38. data/lib/brakeman/tracker/method_info.rb +70 -0
  39. data/lib/brakeman/tracker.rb +33 -4
  40. data/lib/brakeman/util.rb +34 -18
  41. data/lib/brakeman/version.rb +1 -1
  42. data/lib/brakeman/warning_codes.rb +2 -0
  43. data/lib/brakeman.rb +8 -2
  44. data/lib/ruby_parser/bm_sexp.rb +24 -0
  45. metadata +24 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2bc22b69b0b137fe9f223c2469fe6e3857054b0b98621645b52ed94af7fa4886
4
- data.tar.gz: 183f206e691c8251adef49319ca76939a4bf079cf5b14ead1f3f7923754ff9ff
3
+ metadata.gz: cf18736db7a992849a30cccc66f741442e05b695f9ad1bd27fe06f6bc25db849
4
+ data.tar.gz: a884f20cc12305c0856bcc296ddae3aea746b024c232bf11d7988d4e37bd96a3
5
5
  SHA512:
6
- metadata.gz: b902bcfbc2be499f0a892534bf443d88ce92f5a0b47edd31b7ac01a964e9ec13230f03f5ba8bb246dcdee27a7e6bd72b873d2826ce2f6b2486f64999f45b52e8
7
- data.tar.gz: 62f878559fd4aa1f2d96c35742d0c490c0d57c53e07d9a3619675f6519c0fafbaace29e0b616c217ea796132e7810b51b3f06cf1ff60a3a28a34ae9482069f32
6
+ metadata.gz: be93f9f9ba9d808989cbed1bfd450b29c272e806d84707ab0420a8a86b8c797f88d4338f22a1124a462be43ac7bfea605566779321a72d772e9c39d216ded8c3
7
+ data.tar.gz: cf9aa7f34fa5cc737b2e7bbecf625025b50f72f1b3c43ab8f346832145e3cab2245d2af79fd021584ab0aa5fdbb2f854dd41fee8f5a5c891197f1f1e8a570a65
data/CHANGES.md CHANGED
@@ -1,3 +1,51 @@
1
+ # 5.2.0 - 2021-12-15
2
+
3
+ * Initial Rails 7 support
4
+ * Require Ruby 2.5.0+
5
+ * Fix issue with calls to `foo.root` in routes
6
+ * Ignore `I18n.locale` in SQL queries
7
+ * Do not treat `sanitize_sql_like` as safe
8
+ * Add new checks for unsupported Ruby and Rails versions
9
+
10
+ # 5.1.2 - 2021-10-28
11
+
12
+ * Handle cases where enums are not symbols
13
+ * Support newer Haml with ::Haml::AttributeBuilder.build
14
+ * Fix issue where the previous output is still visible (Jason Frey)
15
+ * Fix warning sorting with nil line numbers
16
+ * Update for latest RubyParser (Ryan Davis)
17
+
18
+ # 5.1.1 - 2021-07-19
19
+
20
+ * Unrefactor IgnoreConfig's use of `Brakeman::FilePath`
21
+
22
+ # 5.1.0 - 2021-07-19
23
+
24
+ * Initial support for ActiveRecord enums
25
+ * Support `Hash#include?`
26
+ * Interprocedural dataflow from very simple class methods
27
+ * Fix SARIF report when checks have no description (Eli Block)
28
+ * Add ignored warnings to SARIF report (Eli Block)
29
+ * Add `--sql-safe-methods` option (Esty Scheiner)
30
+ * Update SQL injection check for Rails 6.0/6.1
31
+ * Fix false positive in command injection with `Open3.capture` (Richard Fitzgerald)
32
+ * Fix infinite loop on mixin self-includes (Andrew Szczepanski)
33
+ * Ignore dates in SQL
34
+ * Refactor `cookie?`/`param?` methods (Keenan Brock)
35
+ * Ignore renderables in dynamic render path check (Brad Parker)
36
+ * Support `Array#push`
37
+ * Better `Array#join` support
38
+ * Adjust copy of `--interactive` menu (Elia Schito)
39
+ * Support `Array#*`
40
+ * Better method definition tracking and lookup
41
+ * Support `Hash#values` and `Hash#values_at`
42
+ * Check for user-controlled evaluation even if it's a call target
43
+ * Support `Array#fetch` and `Hash#fetch`
44
+ * Ignore `sanitize_sql_like` in SQL
45
+ * Ignore method calls on numbers in SQL
46
+ * Add GitHub Actions format (Klaus Badelt)
47
+ * Read and parse files in parallel
48
+
1
49
  # 5.0.4 - 2021-06-08
2
50
 
3
51
  (brakeman gem release only)
@@ -418,7 +466,7 @@
418
466
  * Delay loading vendored gems and modifying load path
419
467
  * Avoid warning about SQL injection with `quoted_primary_key`
420
468
  * Support more safe `&.` operations
421
- * Allow multile line regex in `validates_format_of` (Dmitrij Fedorenko)
469
+ * Allow multiple line regex in `validates_format_of` (Dmitrij Fedorenko)
422
470
  * Only consider `if` branches in templates
423
471
  * Avoid overwriting instance/class methods with same name (Tim Wade)
424
472
  * Add `--force-scan` option (Neil Matatall)
data/README.md CHANGED
@@ -66,7 +66,7 @@ Outside of Rails root (note that the output file is relative to path/to/rails/ap
66
66
 
67
67
  Brakeman should work with any version of Rails from 2.3.x to 6.x.
68
68
 
69
- Brakeman can analyze code written with Ruby 1.8 syntax and newer, but requires at least Ruby 2.3.0 to run.
69
+ Brakeman can analyze code written with Ruby 1.8 syntax and newer, but requires at least Ruby 2.4.0 to run.
70
70
 
71
71
  # Basic Options
72
72
 
@@ -28,7 +28,7 @@ module Brakeman
28
28
  # Accepts an array of filenames and paths with the following format and
29
29
  # returns a Regexp to match them:
30
30
  # * "path1/file1.rb" - Matches a specific filename in the project directory.
31
- # * "path1/" - Matches any path that conatains "path1" in the project directory.
31
+ # * "path1/" - Matches any path that contains "path1" in the project directory.
32
32
  # * "/path1/ - Matches any path that is rooted at "path1" in the project directory.
33
33
  #
34
34
  def self.regex_for_paths(paths)
@@ -513,4 +513,14 @@ class Brakeman::BaseCheck < Brakeman::SexpProcessor
513
513
  string_building? exp.target or
514
514
  string_building? exp.first_arg
515
515
  end
516
+
517
+ I18N_CLASS = s(:const, :I18n)
518
+
519
+ def locale_call? exp
520
+ return unless call? exp
521
+
522
+ (exp.target == I18N_CLASS and
523
+ exp.method == :locale) or
524
+ locale_call? exp.target
525
+ end
516
526
  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
 
@@ -0,0 +1,23 @@
1
+ require_relative 'eol_check'
2
+
3
+ class Brakeman::CheckEOLRails < Brakeman::EOLCheck
4
+ Brakeman::Checks.add self
5
+
6
+ @description = "Checks for unsupported versions of Rails"
7
+
8
+ def run_check
9
+ return unless tracker.config.rails_version
10
+
11
+ check_eol_version :rails, RAILS_EOL_DATES
12
+ end
13
+
14
+ RAILS_EOL_DATES = {
15
+ ['2.0.0', '2.3.99'] => Date.new(2013, 6, 25),
16
+ ['3.0.0', '3.2.99'] => Date.new(2016, 6, 30),
17
+ ['4.0.0', '4.2.99'] => Date.new(2017, 4, 27),
18
+ ['5.0.0', '5.0.99'] => Date.new(2018, 5, 9),
19
+ ['5.1.0', '5.1.99'] => Date.new(2019, 8, 25),
20
+ ['5.2.0', '5.2.99'] => Date.new(2022, 6, 1),
21
+ ['6.0.0', '6.0.99'] => Date.new(2023, 6, 1),
22
+ }
23
+ end
@@ -0,0 +1,26 @@
1
+ require_relative 'eol_check'
2
+
3
+ class Brakeman::CheckEOLRuby < Brakeman::EOLCheck
4
+ Brakeman::Checks.add self
5
+
6
+ @description = "Checks for unsupported versions of Ruby"
7
+
8
+ def run_check
9
+ return unless tracker.config.ruby_version
10
+
11
+ check_eol_version :ruby, RUBY_EOL_DATES
12
+ end
13
+
14
+ RUBY_EOL_DATES = {
15
+ ['0.0.0', '1.9.3'] => Date.new(2015, 2, 23),
16
+ ['2.0.0', '2.0.99'] => Date.new(2016, 2, 24),
17
+ ['2.1.0', '2.1.99'] => Date.new(2017, 3, 31),
18
+ ['2.2.0', '2.2.99'] => Date.new(2018, 3, 31),
19
+ ['2.3.0', '2.3.99'] => Date.new(2019, 3, 31),
20
+ ['2.4.0', '2.4.99'] => Date.new(2020, 3, 31),
21
+ ['2.5.0', '2.5.99'] => Date.new(2021, 3, 31),
22
+ ['2.6.0', '2.6.99'] => Date.new(2022, 3, 31),
23
+ ['2.7.0', '2.7.99'] => Date.new(2023, 3, 31),
24
+ ['3.0.0', '2.8.99'] => Date.new(2024, 3, 31),
25
+ }
26
+ end
@@ -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) ||
@@ -74,7 +74,7 @@ class Brakeman::CheckJSONParsing < Brakeman::BaseCheck
74
74
  warning_type = "Denial of Service"
75
75
  confidence = :medium
76
76
  gem_name = "#{name} gem"
77
- message = msg(msg_version(version, gem_name), " has a symbol creation vulnerablity. Upgrade to ")
77
+ message = msg(msg_version(version, gem_name), " has a symbol creation vulnerability. Upgrade to ")
78
78
 
79
79
  if version >= "1.7.0"
80
80
  confidence = :high
@@ -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
@@ -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
@@ -579,6 +591,10 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
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,18 @@ 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 or
632
+ locale_call? exp
633
+ end
634
+
610
635
  QUOTE_METHODS = [:quote, :quote_column_name, :quoted_date, :quote_string, :quote_table_name]
611
636
 
612
637
  def quote_call? exp
@@ -695,4 +720,30 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
695
720
  active_record_models.include? klass
696
721
  end
697
722
  end
723
+
724
+ def number_target? exp
725
+ return unless call? exp
726
+
727
+ if number? exp.target
728
+ true
729
+ elsif call? exp.target
730
+ number_target? exp.target
731
+ else
732
+ false
733
+ end
734
+ end
735
+
736
+ DATE_CLASS = s(:const, :Date)
737
+
738
+ def date_target? exp
739
+ return unless call? exp
740
+
741
+ if exp.target == DATE_CLASS
742
+ true
743
+ elsif call? exp.target
744
+ date_target? exp.target
745
+ else
746
+ false
747
+ end
748
+ end
698
749
  end
@@ -9,7 +9,7 @@ class Brakeman::CheckSymbolDoS < Brakeman::BaseCheck
9
9
 
10
10
  def run_check
11
11
  return if rails_version and rails_version >= "5.0.0"
12
- return if tracker.config.ruby_version >= "2.2"
12
+ return if tracker.config.ruby_version and tracker.config.ruby_version >= "2.2"
13
13
 
14
14
  tracker.find_call(:methods => UNSAFE_METHODS, :nested => true).each do |result|
15
15
  check_unsafe_symbol_creation(result)
@@ -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
@@ -0,0 +1,47 @@
1
+ require 'date'
2
+ require 'brakeman/checks/base_check'
3
+
4
+ # Not used directly - base check for EOLRails and EOLRuby
5
+ class Brakeman::EOLCheck < Brakeman::BaseCheck
6
+ def check_eol_version library, eol_dates
7
+ version = case library
8
+ when :rails
9
+ tracker.config.rails_version
10
+ when :ruby
11
+ tracker.config.ruby_version
12
+ else
13
+ raise 'Implement using tracker.config.gem_version'
14
+ end
15
+
16
+ eol_dates.each do |(start_version, end_version), eol_date|
17
+ if version_between? start_version, end_version, version
18
+ case
19
+ when Date.today >= eol_date
20
+ warn_about_unsupported_version library, eol_date, version
21
+ when (Date.today + 30) >= eol_date
22
+ warn_about_soon_unsupported_version library, eol_date, version, :medium
23
+ when (Date.today + 60) >= eol_date
24
+ warn_about_soon_unsupported_version library, eol_date, version, :low
25
+ end
26
+
27
+ break
28
+ end
29
+ end
30
+ end
31
+
32
+ def warn_about_soon_unsupported_version library, eol_date, version, confidence
33
+ warn warning_type: 'Unmaintained Dependency',
34
+ warning_code: :"pending_eol_#{library}",
35
+ message: msg("Support for ", msg_version(version, library.capitalize), " ends on #{eol_date}"),
36
+ confidence: confidence,
37
+ gem_info: gemfile_or_environment
38
+ end
39
+
40
+ def warn_about_unsupported_version library, eol_date, version
41
+ warn warning_type: 'Unmaintained Dependency',
42
+ warning_code: :"eol_#{library}",
43
+ message: msg("Support for ", msg_version(version, library.capitalize), " ended on #{eol_date}"),
44
+ confidence: :high,
45
+ gem_info: gemfile_or_environment
46
+ end
47
+ end
@@ -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
 
@@ -93,6 +93,14 @@ module Brakeman::Options
93
93
  options[:rails6] = true
94
94
  end
95
95
 
96
+ opts.on "-7", "--rails7", "Force Rails 7 mode" do
97
+ options[:rails3] = true
98
+ options[:rails4] = true
99
+ options[:rails5] = true
100
+ options[:rails6] = true
101
+ options[:rails7] = true
102
+ end
103
+
96
104
  opts.separator ""
97
105
  opts.separator "Scanning options:"
98
106
 
@@ -151,6 +159,11 @@ module Brakeman::Options
151
159
  options[:safe_methods].merge methods.map {|e| e.to_sym }
152
160
  end
153
161
 
162
+ 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|
163
+ options[:sql_safe_methods] ||= Set.new
164
+ options[:sql_safe_methods].merge methods.map {|e| e.to_sym }
165
+ end
166
+
154
167
  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
168
  options[:url_safe_methods] ||= Set.new
156
169
  options[:url_safe_methods].merge methods.map {|e| e.to_sym }
@@ -233,7 +246,7 @@ module Brakeman::Options
233
246
 
234
247
  opts.on "-f",
235
248
  "--format TYPE",
236
- [:pdf, :text, :html, :csv, :tabs, :json, :markdown, :codeclimate, :cc, :plain, :table, :junit, :sarif, :sonar],
249
+ [:pdf, :text, :html, :csv, :tabs, :json, :markdown, :codeclimate, :cc, :plain, :table, :junit, :sarif, :sonar, :github],
237
250
  "Specify output formats. Default is text" do |type|
238
251
 
239
252
  type = "s" if type == :text