brakeman 4.8.0 → 4.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (123) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +39 -1
  3. data/README.md +12 -4
  4. data/bundle/load.rb +4 -4
  5. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.14.2 → ruby_parser-3.15.0}/History.rdoc +35 -0
  6. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.14.2 → ruby_parser-3.15.0}/Manifest.txt +2 -0
  7. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.14.2 → ruby_parser-3.15.0}/README.rdoc +0 -0
  8. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.14.2 → ruby_parser-3.15.0}/compare/normalize.rb +43 -3
  9. data/bundle/ruby/2.7.0/gems/ruby_parser-3.15.0/debugging.md +57 -0
  10. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.14.2 → ruby_parser-3.15.0}/lib/rp_extensions.rb +0 -0
  11. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.14.2 → ruby_parser-3.15.0}/lib/rp_stringscanner.rb +0 -0
  12. data/bundle/ruby/2.7.0/gems/ruby_parser-3.15.0/lib/ruby20_parser.rb +7062 -0
  13. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.14.2 → ruby_parser-3.15.0}/lib/ruby20_parser.y +91 -58
  14. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.14.2 → ruby_parser-3.15.0}/lib/ruby21_parser.rb +2603 -2576
  15. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.14.2 → ruby_parser-3.15.0}/lib/ruby21_parser.y +91 -58
  16. data/bundle/ruby/2.7.0/gems/ruby_parser-3.15.0/lib/ruby22_parser.rb +7160 -0
  17. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.14.2 → ruby_parser-3.15.0}/lib/ruby22_parser.y +91 -58
  18. data/bundle/ruby/2.7.0/gems/ruby_parser-3.15.0/lib/ruby23_parser.rb +7175 -0
  19. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.14.2 → ruby_parser-3.15.0}/lib/ruby23_parser.y +91 -58
  20. data/bundle/ruby/2.7.0/gems/ruby_parser-3.15.0/lib/ruby24_parser.rb +7204 -0
  21. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.14.2 → ruby_parser-3.15.0}/lib/ruby24_parser.y +91 -58
  22. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.14.2/lib/ruby23_parser.rb → ruby_parser-3.15.0/lib/ruby25_parser.rb} +2867 -2826
  23. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.14.2 → ruby_parser-3.15.0}/lib/ruby25_parser.y +91 -58
  24. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.14.2/lib/ruby25_parser.rb → ruby_parser-3.15.0/lib/ruby26_parser.rb} +2432 -2383
  25. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.14.2 → ruby_parser-3.15.0}/lib/ruby26_parser.y +91 -58
  26. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.14.2/lib/ruby24_parser.rb → ruby_parser-3.15.0/lib/ruby27_parser.rb} +2432 -2383
  27. data/bundle/ruby/2.7.0/gems/ruby_parser-3.15.0/lib/ruby27_parser.y +2657 -0
  28. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.14.2 → ruby_parser-3.15.0}/lib/ruby_lexer.rb +72 -40
  29. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.14.2 → ruby_parser-3.15.0}/lib/ruby_lexer.rex +5 -6
  30. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.14.2 → ruby_parser-3.15.0}/lib/ruby_lexer.rex.rb +6 -8
  31. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.14.2 → ruby_parser-3.15.0}/lib/ruby_parser.rb +2 -0
  32. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.14.2 → ruby_parser-3.15.0}/lib/ruby_parser.yy +93 -58
  33. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.14.2 → ruby_parser-3.15.0}/lib/ruby_parser_extras.rb +49 -16
  34. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.14.2 → ruby_parser-3.15.0}/tools/munge.rb +9 -4
  35. data/bundle/ruby/2.7.0/gems/{ruby_parser-3.14.2 → ruby_parser-3.15.0}/tools/ripper.rb +0 -0
  36. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.14.1 → sexp_processor-4.15.1}/History.rdoc +12 -0
  37. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.14.1 → sexp_processor-4.15.1}/Manifest.txt +0 -0
  38. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.14.1 → sexp_processor-4.15.1}/README.rdoc +0 -0
  39. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.14.1 → sexp_processor-4.15.1}/lib/composite_sexp_processor.rb +0 -0
  40. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.14.1 → sexp_processor-4.15.1}/lib/pt_testcase.rb +2 -2
  41. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.14.1 → sexp_processor-4.15.1}/lib/sexp.rb +0 -0
  42. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.14.1 → sexp_processor-4.15.1}/lib/sexp_matcher.rb +4 -7
  43. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.14.1 → sexp_processor-4.15.1}/lib/sexp_processor.rb +1 -1
  44. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.14.1 → sexp_processor-4.15.1}/lib/strict_sexp.rb +0 -0
  45. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.14.1 → sexp_processor-4.15.1}/lib/unique.rb +0 -0
  46. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/CHANGES +4 -0
  47. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/Gemfile +12 -13
  48. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/LICENSE +0 -0
  49. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/README.jp.md +0 -0
  50. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/README.md +0 -0
  51. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim.rb +0 -0
  52. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/code_attributes.rb +0 -0
  53. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/command.rb +13 -13
  54. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/controls.rb +0 -0
  55. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/do_inserter.rb +0 -0
  56. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/embedded.rb +0 -0
  57. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/end_inserter.rb +0 -0
  58. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/engine.rb +0 -0
  59. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/erb_converter.rb +0 -0
  60. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/filter.rb +0 -0
  61. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/grammar.rb +0 -0
  62. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/include.rb +0 -0
  63. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/interpolation.rb +0 -0
  64. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/logic_less.rb +0 -0
  65. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/logic_less/context.rb +0 -0
  66. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/logic_less/filter.rb +0 -0
  67. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/parser.rb +1 -1
  68. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/smart.rb +0 -0
  69. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/smart/escaper.rb +0 -0
  70. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/smart/filter.rb +0 -0
  71. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/smart/parser.rb +0 -0
  72. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/splat/builder.rb +0 -0
  73. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/splat/filter.rb +0 -0
  74. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/template.rb +0 -0
  75. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/translator.rb +0 -0
  76. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/version.rb +1 -1
  77. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/slim.gemspec +0 -0
  78. data/bundle/ruby/2.7.0/gems/{unicode-display_width-1.6.1 → unicode-display_width-1.7.0}/CHANGELOG.md +4 -0
  79. data/bundle/ruby/2.7.0/gems/{unicode-display_width-1.6.1 → unicode-display_width-1.7.0}/MIT-LICENSE.txt +0 -0
  80. data/bundle/ruby/2.7.0/gems/{unicode-display_width-1.6.1 → unicode-display_width-1.7.0}/README.md +1 -1
  81. data/bundle/ruby/2.7.0/gems/unicode-display_width-1.7.0/data/display_width.marshal.gz +0 -0
  82. data/bundle/ruby/2.7.0/gems/{unicode-display_width-1.6.1 → unicode-display_width-1.7.0}/lib/unicode/display_width.rb +0 -0
  83. data/bundle/ruby/2.7.0/gems/{unicode-display_width-1.6.1 → unicode-display_width-1.7.0}/lib/unicode/display_width/constants.rb +2 -2
  84. data/bundle/ruby/2.7.0/gems/{unicode-display_width-1.6.1 → unicode-display_width-1.7.0}/lib/unicode/display_width/index.rb +0 -0
  85. data/bundle/ruby/2.7.0/gems/{unicode-display_width-1.6.1 → unicode-display_width-1.7.0}/lib/unicode/display_width/no_string_ext.rb +0 -0
  86. data/bundle/ruby/2.7.0/gems/{unicode-display_width-1.6.1 → unicode-display_width-1.7.0}/lib/unicode/display_width/string_ext.rb +0 -0
  87. data/lib/brakeman.rb +20 -0
  88. data/lib/brakeman/checks/base_check.rb +1 -1
  89. data/lib/brakeman/checks/check_basic_auth.rb +2 -0
  90. data/lib/brakeman/checks/check_csrf_token_forgery_cve.rb +28 -0
  91. data/lib/brakeman/checks/check_deserialize.rb +21 -1
  92. data/lib/brakeman/checks/check_json_entity_escape.rb +38 -0
  93. data/lib/brakeman/checks/check_mass_assignment.rb +33 -3
  94. data/lib/brakeman/checks/check_model_attr_accessible.rb +1 -1
  95. data/lib/brakeman/checks/check_model_attributes.rb +1 -1
  96. data/lib/brakeman/checks/check_page_caching_cve.rb +37 -0
  97. data/lib/brakeman/checks/check_permit_attributes.rb +1 -1
  98. data/lib/brakeman/checks/check_skip_before_filter.rb +4 -4
  99. data/lib/brakeman/checks/check_sql.rb +1 -1
  100. data/lib/brakeman/checks/check_template_injection.rb +32 -0
  101. data/lib/brakeman/commandline.rb +25 -1
  102. data/lib/brakeman/options.rb +21 -1
  103. data/lib/brakeman/processors/alias_processor.rb +2 -3
  104. data/lib/brakeman/processors/lib/call_conversion_helper.rb +1 -1
  105. data/lib/brakeman/processors/lib/find_all_calls.rb +28 -13
  106. data/lib/brakeman/processors/lib/render_helper.rb +3 -1
  107. data/lib/brakeman/report.rb +7 -0
  108. data/lib/brakeman/report/ignore/config.rb +4 -0
  109. data/lib/brakeman/report/report_sarif.rb +114 -0
  110. data/lib/brakeman/report/report_text.rb +37 -16
  111. data/lib/brakeman/scanner.rb +4 -1
  112. data/lib/brakeman/tracker.rb +3 -1
  113. data/lib/brakeman/tracker/config.rb +6 -4
  114. data/lib/brakeman/tracker/constants.rb +8 -7
  115. data/lib/brakeman/util.rb +16 -0
  116. data/lib/brakeman/version.rb +1 -1
  117. data/lib/brakeman/warning_codes.rb +7 -0
  118. metadata +89 -82
  119. data/bundle/ruby/2.7.0/gems/ruby_parser-3.14.2/debugging.md +0 -18
  120. data/bundle/ruby/2.7.0/gems/ruby_parser-3.14.2/lib/ruby20_parser.rb +0 -7042
  121. data/bundle/ruby/2.7.0/gems/ruby_parser-3.14.2/lib/ruby22_parser.rb +0 -7146
  122. data/bundle/ruby/2.7.0/gems/ruby_parser-3.14.2/lib/ruby26_parser.rb +0 -7195
  123. data/bundle/ruby/2.7.0/gems/unicode-display_width-1.6.1/data/display_width.marshal.gz +0 -0
@@ -1,5 +1,9 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 1.7.0
4
+
5
+ - Unicode 13
6
+
3
7
  ## 1.6.1
4
8
 
5
9
  - Fix that ambiguous and overwrite options where ignored for emoji-measuring
@@ -2,7 +2,7 @@
2
2
 
3
3
  Determines the monospace display width of a string in Ruby. Implementation based on [EastAsianWidth.txt](https://www.unicode.org/Public/UNIDATA/EastAsianWidth.txt) and other data, 100% in Ruby. Other than [wcwidth()](https://github.com/janlelis/wcswidth-ruby), which fulfills a similar purpose, it does not rely on the OS vendor to provide an up-to-date method for measuring string width.
4
4
 
5
- Unicode version: **12.1.0** (May 2019)
5
+ Unicode version: **13.0.0** (March 2020)
6
6
 
7
7
  Supported Rubies: **2.7**, **2.6**, **2.5**, **2.4**
8
8
 
@@ -1,7 +1,7 @@
1
1
  module Unicode
2
2
  module DisplayWidth
3
- VERSION = '1.6.1'
4
- UNICODE_VERSION = "12.1.0".freeze
3
+ VERSION = '1.7.0'
4
+ UNICODE_VERSION = "13.0.0".freeze
5
5
  DATA_DIRECTORY = File.expand_path(File.dirname(__FILE__) + '/../../../data/').freeze
6
6
  INDEX_FILENAME = (DATA_DIRECTORY + '/display_width.marshal.gz').freeze
7
7
  end
@@ -20,6 +20,10 @@ module Brakeman
20
20
  #option is set
21
21
  Errors_Found_Exit_Code = 7
22
22
 
23
+ #Exit code returned when an ignored warning has no note and
24
+ #--ensure-ignore-notes is set
25
+ Empty_Ignore_Note_Exit_Code = 8
26
+
23
27
  @debug = false
24
28
  @quiet = false
25
29
  @loaded_dependencies = []
@@ -233,6 +237,8 @@ module Brakeman
233
237
  [:to_table]
234
238
  when :junit, :to_junit
235
239
  [:to_junit]
240
+ when :sarif, :to_sarif
241
+ [:to_sarif]
236
242
  else
237
243
  [:to_text]
238
244
  end
@@ -262,6 +268,8 @@ module Brakeman
262
268
  :to_table
263
269
  when /\.junit$/i
264
270
  :to_junit
271
+ when /\.sarif$/i
272
+ :to_sarif
265
273
  else
266
274
  :to_text
267
275
  end
@@ -498,6 +506,18 @@ module Brakeman
498
506
  end
499
507
  end
500
508
 
509
+ # Returns an array of alert fingerprints for any ignored warnings without
510
+ # notes found in the specified ignore file (if it exists).
511
+ def self.ignore_file_entries_with_empty_notes file
512
+ return [] unless file
513
+
514
+ require 'brakeman/report/ignore/config'
515
+
516
+ config = IgnoreConfig.new(file, nil)
517
+ config.read_from_file
518
+ config.already_ignored_entries_with_empty_notes.map { |i| i[:fingerprint] }
519
+ end
520
+
501
521
  def self.filter_warnings tracker, options
502
522
  require 'brakeman/report/ignore/config'
503
523
 
@@ -467,7 +467,7 @@ class Brakeman::BaseCheck < Brakeman::SexpProcessor
467
467
  end
468
468
 
469
469
  def gemfile_or_environment gem_name = :rails
470
- if gem_name and info = tracker.config.get_gem(gem_name)
470
+ if gem_name and info = tracker.config.get_gem(gem_name.to_sym)
471
471
  info
472
472
  elsif @app_tree.exists?("Gemfile")
473
473
  @app_tree.file_path "Gemfile"
@@ -57,6 +57,8 @@ class Brakeman::CheckBasicAuth < Brakeman::BaseCheck
57
57
 
58
58
  # Check if the block of a result contains a comparison of password to string
59
59
  def include_password_literal? result
60
+ return false if result[:block_args].nil?
61
+
60
62
  @password_var = result[:block_args].last
61
63
  @include_password = false
62
64
  process result[:block]
@@ -0,0 +1,28 @@
1
+ require 'brakeman/checks/base_check'
2
+
3
+ class Brakeman::CheckCSRFTokenForgeryCVE < Brakeman::BaseCheck
4
+ Brakeman::Checks.add self
5
+
6
+ @description = "Checks for versions with CSRF token forgery vulnerability (CVE-2020-8166)"
7
+
8
+ def run_check
9
+ fix_version = case
10
+ when version_between?('0.0.0', '5.2.4.2')
11
+ '5.2.4.3'
12
+ when version_between?('6.0.0', '6.0.3')
13
+ '6.0.3.1'
14
+ else
15
+ nil
16
+ end
17
+
18
+ if fix_version
19
+ warn :warning_type => "Cross-Site Request Forgery",
20
+ :warning_code => :CVE_2020_8166,
21
+ :message => msg(msg_version(rails_version), " has a vulnerability that may allow CSRF token forgery. Upgrade to ", msg_version(fix_version), " or patch"),
22
+ :confidence => :medium,
23
+ :gem_info => gemfile_or_environment,
24
+ :link => "https://groups.google.com/g/rubyonrails-security/c/NOjKiGeXUgw"
25
+ end
26
+ end
27
+ end
28
+
@@ -13,7 +13,23 @@ class Brakeman::CheckDeserialize < Brakeman::BaseCheck
13
13
  end
14
14
 
15
15
  def check_yaml
16
- check_methods :YAML, :load, :load_documents, :load_stream, :parse_documents, :parse_stream
16
+ check_methods :YAML, :load_documents, :load_stream, :parse_documents, :parse_stream
17
+
18
+ # Check for safe_yaml gem use with YAML.load(..., safe: true)
19
+ if uses_safe_yaml?
20
+ tracker.find_call(target: :YAML, method: :load).each do |result|
21
+ call = result[:call]
22
+ options = call.second_arg
23
+
24
+ if hash? options and true? hash_access(options, :safe)
25
+ next
26
+ else
27
+ check_deserialize result, :YAML
28
+ end
29
+ end
30
+ else
31
+ check_methods :YAML, :load
32
+ end
17
33
  end
18
34
 
19
35
  def check_csv
@@ -102,4 +118,8 @@ class Brakeman::CheckDeserialize < Brakeman::BaseCheck
102
118
 
103
119
  false
104
120
  end
121
+
122
+ def uses_safe_yaml?
123
+ tracker.config.has_gem? :safe_yaml
124
+ end
105
125
  end
@@ -0,0 +1,38 @@
1
+ require 'brakeman/checks/base_check'
2
+
3
+ class Brakeman::CheckJSONEntityEscape < Brakeman::BaseCheck
4
+ Brakeman::Checks.add self
5
+
6
+ @description = "Check if HTML escaping is disabled for JSON output"
7
+
8
+ def run_check
9
+ check_config_setting
10
+ check_manual_disable
11
+ end
12
+
13
+ def check_config_setting
14
+ if false? tracker.config.rails.dig(:active_support, :escape_html_entities_in_json)
15
+ warn :warning_type => "Cross-Site Scripting",
16
+ :warning_code => :json_html_escape_config,
17
+ :message => msg("HTML entities in JSON are not escaped by default"),
18
+ :confidence => :medium,
19
+ :file => "config/environments/production.rb",
20
+ :line => 1
21
+ end
22
+ end
23
+
24
+ def check_manual_disable
25
+ tracker.find_call(targets: [:ActiveSupport, :'ActiveSupport::JSON::Encoding'], method: :escape_html_entities_in_json=).each do |result|
26
+ setting = result[:call].first_arg
27
+
28
+ if false? setting
29
+ warn :result => result,
30
+ :warning_type => "Cross-Site Scripting",
31
+ :warning_code => :json_html_escape_module,
32
+ :message => msg("HTML entities in JSON are not escaped by default"),
33
+ :confidence => :medium,
34
+ :file => "config/environments/production.rb"
35
+ end
36
+ end
37
+ end
38
+ end
@@ -17,6 +17,7 @@ class Brakeman::CheckMassAssignment < Brakeman::BaseCheck
17
17
  def run_check
18
18
  check_mass_assignment
19
19
  check_permit!
20
+ check_permit_all_parameters
20
21
  end
21
22
 
22
23
  def find_mass_assign_calls
@@ -159,12 +160,27 @@ class Brakeman::CheckMassAssignment < Brakeman::BaseCheck
159
160
  # Look for and warn about uses of Parameters#permit! for mass assignment
160
161
  def check_permit!
161
162
  tracker.find_call(:method => :permit!, :nested => true).each do |result|
162
- if params? result[:call].target and not result[:chain].include? :slice
163
- warn_on_permit! result
163
+ if params? result[:call].target
164
+ unless inside_safe_method? result or calls_slice? result
165
+ warn_on_permit! result
166
+ end
164
167
  end
165
168
  end
166
169
  end
167
170
 
171
+ # Ignore blah_some_path(params.permit!)
172
+ def inside_safe_method? result
173
+ parent_call = result.dig(:parent, :call)
174
+
175
+ call? parent_call and
176
+ parent_call.method.match(/_path$/)
177
+ end
178
+
179
+ def calls_slice? result
180
+ result[:chain].include? :slice or
181
+ (result[:full_call] and result[:full_call][:chain].include? :slice)
182
+ end
183
+
168
184
  # Look for actual use of params in mass assignment to avoid
169
185
  # warning about uses of Parameters#permit! without any mass assignment
170
186
  # or when mass assignment is restricted by model instead.
@@ -190,7 +206,21 @@ class Brakeman::CheckMassAssignment < Brakeman::BaseCheck
190
206
  warn :result => result,
191
207
  :warning_type => "Mass Assignment",
192
208
  :warning_code => :mass_assign_permit!,
193
- :message => "Parameters should be whitelisted for mass assignment",
209
+ :message => msg('Specify exact keys allowed for mass assignment instead of using ', msg_code('permit!'), ' which allows any keys'),
194
210
  :confidence => confidence
195
211
  end
212
+
213
+ def check_permit_all_parameters
214
+ tracker.find_call(target: :"ActionController::Parameters", method: :permit_all_parameters=).each do |result|
215
+ call = result[:call]
216
+
217
+ if true? call.first_arg
218
+ warn :result => result,
219
+ :warning_type => "Mass Assignment",
220
+ :warning_code => :mass_assign_permit_all,
221
+ :message => msg('Mass assignment is globally enabled. Disable and specify exact keys using ', msg_code('params.permit'), ' instead'),
222
+ :confidence => :high
223
+ end
224
+ end
225
+ end
196
226
  end
@@ -8,7 +8,7 @@ require 'brakeman/checks/base_check'
8
8
  class Brakeman::CheckModelAttrAccessible < Brakeman::BaseCheck
9
9
  Brakeman::Checks.add self
10
10
 
11
- @description = "Reports models which have dangerous attributes defined under the attr_accessible whitelist."
11
+ @description = "Reports models which have dangerous attributes defined via attr_accessible"
12
12
 
13
13
  SUSP_ATTRS = [
14
14
  [:admin, :high], # Very dangerous unless some Rails authorization used
@@ -8,7 +8,7 @@ class Brakeman::CheckModelAttributes < Brakeman::BaseCheck
8
8
  @description = "Reports models which do not use attr_restricted and warns on models that use attr_protected"
9
9
 
10
10
  def run_check
11
- return if mass_assign_disabled?
11
+ return if mass_assign_disabled? or tracker.config.has_gem?(:protected_attributes)
12
12
 
13
13
  #Roll warnings into one warning for all models
14
14
  if tracker.options[:collapse_mass_assignment]
@@ -0,0 +1,37 @@
1
+ require 'brakeman/checks/base_check'
2
+
3
+ class Brakeman::CheckPageCachingCVE < Brakeman::BaseCheck
4
+ Brakeman::Checks.add self
5
+
6
+ @description = "Check for page caching vulnerability (CVE-2020-8159)"
7
+
8
+ def run_check
9
+ gem_name = 'actionpack-page_caching'
10
+ gem_version = tracker.config.gem_version(gem_name.to_sym)
11
+ upgrade_version = '1.2.2'
12
+ cve = 'CVE-2020-8159'
13
+
14
+ return unless gem_version and version_between?('0.0.0', '1.2.1', gem_version)
15
+
16
+ message = msg("Directory traversal vulnerability in ", msg_version(gem_version, gem_name), " ", msg_cve(cve), ". Upgrade to ", msg_version(upgrade_version, gem_name))
17
+
18
+ if uses_caches_page?
19
+ confidence = :high
20
+ else
21
+ confidence = :weak
22
+ end
23
+
24
+ warn :warning_type => 'Directory Traversal',
25
+ :warning_code => :CVE_2020_8159,
26
+ :message => message,
27
+ :confidence => confidence,
28
+ :link_path => 'https://groups.google.com/d/msg/rubyonrails-security/CFRVkEytdP8/c5gmICECAgAJ',
29
+ :gem_info => gemfile_or_environment(gem_name)
30
+ end
31
+
32
+ def uses_caches_page?
33
+ tracker.controllers.any? do |name, controller|
34
+ controller.options.has_key? :caches_page
35
+ end
36
+ end
37
+ end
@@ -3,7 +3,7 @@ require 'brakeman/checks/base_check'
3
3
  class Brakeman::CheckPermitAttributes < Brakeman::BaseCheck
4
4
  Brakeman::Checks.add self
5
5
 
6
- @description = "Warn on potentially dangerous attributes whitelisted via permit"
6
+ @description = "Warn on potentially dangerous attributes allowed via permit"
7
7
 
8
8
  SUSPICIOUS_KEYS = {
9
9
  admin: :high,
@@ -4,8 +4,8 @@ require 'brakeman/checks/base_check'
4
4
  #
5
5
  # skip_before_filter :verify_authenticity_token, :except => [...]
6
6
  #
7
- #which is essentially a blacklist approach (no actions are checked EXCEPT the
8
- #ones listed) versus a whitelist approach (ONLY the actions listed will skip
7
+ #which is essentially a skip-by-default approach (no actions are checked EXCEPT the
8
+ #ones listed) versus a enforce-by-default approach (ONLY the actions listed will skip
9
9
  #the check)
10
10
  class Brakeman::CheckSkipBeforeFilter < Brakeman::BaseCheck
11
11
  Brakeman::Checks.add self
@@ -26,7 +26,7 @@ class Brakeman::CheckSkipBeforeFilter < Brakeman::BaseCheck
26
26
  warn :class => controller.name, #ugh this should be a controller warning, too
27
27
  :warning_type => "Cross-Site Request Forgery",
28
28
  :warning_code => :csrf_blacklist,
29
- :message => msg("Use whitelist (", msg_code(":only => [..]"), ") when skipping CSRF check"),
29
+ :message => msg("List specific actions (", msg_code(":only => [..]"), ") when skipping CSRF check"),
30
30
  :code => filter,
31
31
  :confidence => :medium,
32
32
  :file => controller.file
@@ -35,7 +35,7 @@ class Brakeman::CheckSkipBeforeFilter < Brakeman::BaseCheck
35
35
  warn :controller => controller.name,
36
36
  :warning_code => :auth_blacklist,
37
37
  :warning_type => "Authentication",
38
- :message => msg("Use whitelist (", msg_code(":only => [..]"), ") when skipping authentication"),
38
+ :message => msg("List specific actions (", msg_code(":only => [..]"), ") when skipping authentication"),
39
39
  :code => filter,
40
40
  :confidence => :medium,
41
41
  :link_path => "authentication_whitelist",
@@ -393,7 +393,7 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
393
393
  nil
394
394
  end
395
395
 
396
- TO_STRING_METHODS = [:to_s, :strip_heredoc]
396
+ TO_STRING_METHODS = [:chomp, :to_s, :squish, :strip, :strip_heredoc]
397
397
 
398
398
  #Returns value if interpolated value is not something safe
399
399
  def unsafe_string_interp? exp
@@ -0,0 +1,32 @@
1
+ require 'brakeman/checks/base_check'
2
+
3
+ class Brakeman::CheckTemplateInjection < Brakeman::BaseCheck
4
+ Brakeman::Checks.add self
5
+
6
+ @description = "Searches for evaluation of user input through template injection"
7
+
8
+ #Process calls
9
+ def run_check
10
+ Brakeman.debug "Finding ERB.new calls"
11
+ erb_calls = tracker.find_call :target => :ERB, :method => :new, :nested => true
12
+
13
+ Brakeman.debug "Processing ERB.new calls"
14
+ erb_calls.each do |call|
15
+ process_result call
16
+ end
17
+ end
18
+
19
+ #Warns if eval includes user input
20
+ def process_result result
21
+ return unless original? result
22
+
23
+ if input = include_user_input?(result[:call].arglist)
24
+ warn :result => result,
25
+ :warning_type => "Template Injection",
26
+ :warning_code => :erb_template_injection,
27
+ :message => msg(msg_input(input), " used directly in ", msg_code("ERB"), " template, which might enable remote code execution"),
28
+ :user_input => input,
29
+ :confidence => :high
30
+ end
31
+ end
32
+ end
@@ -102,6 +102,13 @@ module Brakeman
102
102
  app_path = "."
103
103
  end
104
104
 
105
+ if options[:ensure_ignore_notes] and options[:previous_results_json]
106
+ warn '[Notice] --ensure-ignore-notes may not be used at the same ' \
107
+ 'time as --compare. Deactivating --ensure-ignore-notes. ' \
108
+ 'Please see `brakeman --help` for valid options'
109
+ options[:ensure_ignore_notes] = false
110
+ end
111
+
105
112
  return options, app_path
106
113
  end
107
114
 
@@ -115,7 +122,20 @@ module Brakeman
115
122
 
116
123
  # Runs a regular report based on the options provided.
117
124
  def regular_report options
118
- tracker = run_brakeman options
125
+ tracker = run_brakeman options
126
+
127
+ ensure_ignore_notes_failed = false
128
+ if tracker.options[:ensure_ignore_notes]
129
+ fingerprints = Brakeman::ignore_file_entries_with_empty_notes tracker.ignored_filter&.file
130
+
131
+ unless fingerprints.empty?
132
+ ensure_ignore_notes_failed = true
133
+ warn '[Error] Notes required for all ignored warnings when ' \
134
+ '--ensure-ignore-notes is set. No notes provided for these ' \
135
+ 'warnings: '
136
+ fingerprints.each { |f| warn f }
137
+ end
138
+ end
119
139
 
120
140
  if tracker.options[:exit_on_warn] and not tracker.filtered_warnings.empty?
121
141
  quit Brakeman::Warnings_Found_Exit_Code
@@ -124,6 +144,10 @@ module Brakeman
124
144
  if tracker.options[:exit_on_error] and tracker.errors.any?
125
145
  quit Brakeman::Errors_Found_Exit_Code
126
146
  end
147
+
148
+ if ensure_ignore_notes_failed
149
+ quit Brakeman::Empty_Ignore_Note_Exit_Code
150
+ end
127
151
  end
128
152
 
129
153
  # Actually run Brakeman.