brakeman 4.8.2 → 4.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +13 -0
  3. data/bundle/load.rb +2 -2
  4. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.14.1 → sexp_processor-4.15.0}/History.rdoc +6 -0
  5. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.14.1 → sexp_processor-4.15.0}/Manifest.txt +0 -0
  6. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.14.1 → sexp_processor-4.15.0}/README.rdoc +0 -0
  7. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.14.1 → sexp_processor-4.15.0}/lib/composite_sexp_processor.rb +0 -0
  8. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.14.1 → sexp_processor-4.15.0}/lib/pt_testcase.rb +0 -0
  9. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.14.1 → sexp_processor-4.15.0}/lib/sexp.rb +0 -0
  10. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.14.1 → sexp_processor-4.15.0}/lib/sexp_matcher.rb +4 -7
  11. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.14.1 → sexp_processor-4.15.0}/lib/sexp_processor.rb +1 -1
  12. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.14.1 → sexp_processor-4.15.0}/lib/strict_sexp.rb +0 -0
  13. data/bundle/ruby/2.7.0/gems/{sexp_processor-4.14.1 → sexp_processor-4.15.0}/lib/unique.rb +0 -0
  14. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/CHANGES +4 -0
  15. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/Gemfile +12 -13
  16. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/LICENSE +0 -0
  17. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/README.jp.md +0 -0
  18. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/README.md +0 -0
  19. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim.rb +0 -0
  20. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/code_attributes.rb +0 -0
  21. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/command.rb +13 -13
  22. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/controls.rb +0 -0
  23. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/do_inserter.rb +0 -0
  24. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/embedded.rb +0 -0
  25. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/end_inserter.rb +0 -0
  26. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/engine.rb +0 -0
  27. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/erb_converter.rb +0 -0
  28. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/filter.rb +0 -0
  29. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/grammar.rb +0 -0
  30. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/include.rb +0 -0
  31. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/interpolation.rb +0 -0
  32. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/logic_less.rb +0 -0
  33. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/logic_less/context.rb +0 -0
  34. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/logic_less/filter.rb +0 -0
  35. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/parser.rb +1 -1
  36. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/smart.rb +0 -0
  37. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/smart/escaper.rb +0 -0
  38. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/smart/filter.rb +0 -0
  39. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/smart/parser.rb +0 -0
  40. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/splat/builder.rb +0 -0
  41. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/splat/filter.rb +0 -0
  42. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/template.rb +0 -0
  43. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/translator.rb +0 -0
  44. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/lib/slim/version.rb +1 -1
  45. data/bundle/ruby/2.7.0/gems/{slim-4.0.1 → slim-4.1.0}/slim.gemspec +0 -0
  46. data/lib/brakeman.rb +16 -0
  47. data/lib/brakeman/checks/check_csrf_token_forgery_cve.rb +28 -0
  48. data/lib/brakeman/checks/check_deserialize.rb +21 -1
  49. data/lib/brakeman/checks/check_mass_assignment.rb +19 -4
  50. data/lib/brakeman/checks/check_model_attr_accessible.rb +1 -1
  51. data/lib/brakeman/checks/check_permit_attributes.rb +1 -1
  52. data/lib/brakeman/checks/check_skip_before_filter.rb +4 -4
  53. data/lib/brakeman/checks/check_template_injection.rb +32 -0
  54. data/lib/brakeman/commandline.rb +25 -1
  55. data/lib/brakeman/options.rb +4 -0
  56. data/lib/brakeman/processors/alias_processor.rb +2 -3
  57. data/lib/brakeman/processors/lib/find_all_calls.rb +27 -12
  58. data/lib/brakeman/report/ignore/config.rb +4 -0
  59. data/lib/brakeman/scanner.rb +4 -1
  60. data/lib/brakeman/tracker.rb +3 -1
  61. data/lib/brakeman/tracker/constants.rb +8 -7
  62. data/lib/brakeman/util.rb +16 -0
  63. data/lib/brakeman/version.rb +1 -1
  64. data/lib/brakeman/warning_codes.rb +2 -0
  65. metadata +46 -44
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 31ceb768759fdfd53c78753d73ea57c6f35e655dd8ef88e9a34c75fa42f74c65
4
- data.tar.gz: d68f7d634d8f2c4f62e1820760f09284ecbfbf44fed9d24e223743c3cc3fd773
3
+ metadata.gz: 2c34a5dde886bb8433eaf2b407a3be4a53cf7cde9c6c439a1438b25caf359096
4
+ data.tar.gz: 46689fbf4debd45a041ac0eaff08b06bee7f03c90707332a0ee145ba18884328
5
5
  SHA512:
6
- metadata.gz: 96c55e31c70b374516e6a54e080548b3138c475e5b9e1752095b8536f72b8ab14e18984417fc7e928d3daaacbfbc9ae230fb093c67e5b42fb66cb14d7c920880
7
- data.tar.gz: 1f83b5051e1bfc1af48a64d92c67719219fe92adcadcc7aed04113682a9f2d463f0bb9aface369baf691114aeb631662c07218365c67bd06dc0414db588e0c8d
6
+ metadata.gz: 5efc78c8ae5aa23e9557fd60e97799119d0a124ba70c5f7fb8dea801e4273071cad44aebc8bd8b019cb01790f17dcdc737998d52835332ac705898582084eb3e
7
+ data.tar.gz: 1c503845173d3f1b199f60451f7a7ce3f0844689097cfbd650cca058934cbbfd6cc8de0f292de5f562359dcc845acaa070d0b6aad626faf5bed28405c82b8622
data/CHANGES.md CHANGED
@@ -1,3 +1,16 @@
1
+ # 4.9.0 - 2020-08-04
2
+
3
+ * Add check for CVE-2020-8166 (Jamie Finnigan)
4
+ * Avoid warning when `safe_yaml` is used via `YAML.load(..., safe: true)`
5
+ * Add check for user input in `ERB.new` (Matt Hickman)
6
+ * Add `--ensure-ignore-notes` (Eli Block)
7
+ * Remove whitelist/blacklist language, add clarifications
8
+ * Do not warn about mass assignment with `params.permit!.slice`
9
+ * Add "full call" information to call index results
10
+ * Ignore `params.permit!` in path helpers
11
+ * Treat `Dir.glob` as safe source of values in guards
12
+ * Always scan `environment.rb`
13
+
1
14
  # 4.8.2 - 2020-05-12
2
15
 
3
16
  * Add check for CVE-2020-8159
@@ -1,8 +1,8 @@
1
1
  path = File.expand_path('../..', __FILE__)
2
2
  $:.unshift "#{path}/bundle/ruby/2.7.0/gems/temple-0.8.2/lib"
3
3
  $:.unshift "#{path}/bundle/ruby/2.7.0/gems/unicode-display_width-1.7.0/lib"
4
- $:.unshift "#{path}/bundle/ruby/2.7.0/gems/slim-4.0.1/lib"
5
4
  $:.unshift "#{path}/bundle/ruby/2.7.0/gems/tilt-2.0.10/lib"
5
+ $:.unshift "#{path}/bundle/ruby/2.7.0/gems/slim-4.1.0/lib"
6
6
  $:.unshift "#{path}/bundle/ruby/2.7.0/gems/highline-2.0.3/lib"
7
7
  $:.unshift "#{path}/bundle/ruby/2.7.0/gems/ruby_parser-3.14.2/lib"
8
8
  $:.unshift "#{path}/bundle/ruby/2.7.0/gems/ruby2ruby-2.4.4/lib"
@@ -10,5 +10,5 @@ $:.unshift "#{path}/bundle/ruby/2.7.0/gems/terminal-table-1.8.0/lib"
10
10
  $:.unshift "#{path}/bundle/ruby/2.7.0/gems/haml-5.1.2/lib"
11
11
  $:.unshift "#{path}/bundle/ruby/2.7.0/gems/ruby_parser-legacy-1.0.0/lib"
12
12
  $:.unshift "#{path}/bundle/ruby/2.7.0/gems/erubis-2.7.0/lib"
13
- $:.unshift "#{path}/bundle/ruby/2.7.0/gems/sexp_processor-4.14.1/lib"
13
+ $:.unshift "#{path}/bundle/ruby/2.7.0/gems/sexp_processor-4.15.0/lib"
14
14
  $:.unshift "#{path}/bundle/ruby/2.7.0/gems/safe_yaml-1.0.5/lib"
@@ -1,3 +1,9 @@
1
+ === 4.15.0 / 2020-06-09
2
+
3
+ * 1 minor enhancement:
4
+
5
+ * Added `child` and `include` to Sexp::Matcher.parse language.
6
+
1
7
  === 4.14.1 / 2020-02-09
2
8
 
3
9
  * 2 bug fixes:
@@ -455,7 +455,7 @@ class Sexp #:nodoc:
455
455
  # | NAME:name => name.to_sym
456
456
  # UP_NAME: /[A-Z]\w*/
457
457
  # NAME : /:?[\w?!=~-]+/
458
- # CMD : "t" | "k" | "m" | "atom" | "not?" | "-" | "any"
458
+ # CMD : t | k | m | atom | not? | - | any | child | include
459
459
 
460
460
  def parse_sexp
461
461
  token = next_token
@@ -505,7 +505,7 @@ class Sexp #:nodoc:
505
505
  ##
506
506
  # A collection of allowed commands to convert into matchers.
507
507
 
508
- ALLOWED = [:t, :m, :k, :atom, :not?, :-, :any].freeze
508
+ ALLOWED = [:t, :m, :k, :atom, :not?, :-, :any, :child, :include].freeze
509
509
 
510
510
  ##
511
511
  # Parses a balanced command. A command is denoted by square
@@ -760,11 +760,8 @@ class Sexp #:nodoc:
760
760
  # +child+.
761
761
 
762
762
  def satisfy? o
763
- if child.satisfy? o
764
- true
765
- elsif o.kind_of? Sexp
766
- o.search_each(child).any?
767
- end
763
+ child.satisfy?(o) ||
764
+ (o.kind_of?(Sexp) && o.search_each(child).any?)
768
765
  end
769
766
 
770
767
  def == o # :nodoc:
@@ -34,7 +34,7 @@ require "sexp"
34
34
  class SexpProcessor
35
35
 
36
36
  # duh
37
- VERSION = "4.14.1"
37
+ VERSION = "4.15.0"
38
38
 
39
39
  ##
40
40
  # Automatically shifts off the Sexp type before handing the
@@ -1,3 +1,7 @@
1
+ 4.1.0 (2020-05-07)
2
+ * Add support for Tailwind CSS - #841
3
+ * Update dependencies and testing
4
+
1
5
  4.0.1 (2018-09-02)
2
6
 
3
7
  * Fix incompatibility issue with Slim Include plugin and new ability to specifiy attributes for embedded engines #819
@@ -7,6 +7,12 @@ group :test do
7
7
  gem 'rack-test'
8
8
  end
9
9
 
10
+ group :perf do
11
+ gem 'benchmark-ips'
12
+ gem 'erubis'
13
+ gem 'haml'
14
+ end
15
+
10
16
  if ENV['TRAVIS']
11
17
  gem 'rails-controller-testing'
12
18
  end
@@ -30,19 +36,12 @@ if ENV['RAILS']
30
36
  else
31
37
  gem 'rails', "= #{ENV['RAILS']}"
32
38
  end
33
- end
34
39
 
35
- #Choose minitest 4.7.x for sinatra < 1.4.6 or rails 3 and 4.0 otherwise go for newer version
36
- if (ENV['SINATRA'] && ENV['SINATRA'] < '1.4.6') || (ENV['RAILS'] && ENV['RAILS'].match(/^(3|4\.0)/))
37
- gem 'minitest', '~> 4.7.4'
38
- else
39
- gem 'minitest', '~> 5.1'
40
+ gem 'slim-rails', require: false
40
41
  end
41
42
 
42
- #Ruby >= 2.2.0 has removed test/unit from Stdlib
43
- if RUBY_VERSION >= '2.2.0'
44
- gem 'test-unit', platforms: :mri
45
- end
43
+ gem 'test-unit', '~> 3.3', '>= 3.3.5'
44
+ gem 'minitest', '~> 5.14'
46
45
 
47
46
  if RUBY_ENGINE == 'rbx' && !ENV['TRAVIS']
48
47
  gem 'psych'
@@ -56,9 +55,9 @@ if ENV['SINATRA']
56
55
  end
57
56
  end
58
57
 
59
- gem 'rake', '>= 0.8.7'
60
- gem 'sass', '>= 3.1.0'
61
- gem 'kramdown'
58
+ gem 'rake', '~> 13.0', '>= 13.0.1'
59
+ gem 'sassc', '~> 2.2', '>= 2.2.1'
60
+ gem 'kramdown', '~> 2.1'
62
61
 
63
62
  if ENV['TASK'] == 'bench'
64
63
  gem 'benchmark-ips'
@@ -110,19 +110,19 @@ module Slim
110
110
  Template.new(@options[:file]) { @options[:input].read }.render(nil, locals)
111
111
  end
112
112
 
113
- rescue Exception => ex
114
- raise ex if @options[:trace] || SystemExit === ex
115
- $stderr.print "#{ex.class}: " if ex.class != RuntimeError
116
- $stderr.puts ex.message
117
- $stderr.puts ' Use --trace for backtrace.'
118
- exit 1
119
- else
120
- unless @options[:output]
121
- file = args.shift
122
- @options[:output] = file ? File.open(file, 'w') : $stdout
123
- end
124
- @options[:output].puts(result)
125
- exit 0
113
+ rescue Exception => ex
114
+ raise ex if @options[:trace] || SystemExit === ex
115
+ $stderr.print "#{ex.class}: " if ex.class != RuntimeError
116
+ $stderr.puts ex.message
117
+ $stderr.puts ' Use --trace for backtrace.'
118
+ exit 1
119
+ else
120
+ unless @options[:output]
121
+ file = args.shift
122
+ @options[:output] = file ? File.open(file, 'w') : $stdout
123
+ end
124
+ @options[:output].puts(result)
125
+ exit 0
126
126
  end
127
127
  end
128
128
  end
@@ -70,7 +70,7 @@ module Slim
70
70
  end
71
71
  end
72
72
  keys = Regexp.union @attr_shortcut.keys.sort_by {|k| -k.size }
73
- @attr_shortcut_re = /\A(#{keys}+)((?:\p{Word}|-)*)/
73
+ @attr_shortcut_re = /\A(#{keys}+)((?:\p{Word}|-|\/\d+|:(\w|-)+)*)/
74
74
  keys = Regexp.union @tag_shortcut.keys.sort_by {|k| -k.size }
75
75
  @tag_re = /\A(?:#{keys}|\*(?=[^\s]+)|(\p{Word}(?:\p{Word}|:|-)*\p{Word}|\p{Word}+))/
76
76
  keys = Regexp.escape @code_attr_delims.keys.join
@@ -1,5 +1,5 @@
1
1
  module Slim
2
2
  # Slim version string
3
3
  # @api public
4
- VERSION = '4.0.1'
4
+ VERSION = '4.1.0'
5
5
  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 = []
@@ -498,6 +502,18 @@ module Brakeman
498
502
  end
499
503
  end
500
504
 
505
+ # Returns an array of alert fingerprints for any ignored warnings without
506
+ # notes found in the specified ignore file (if it exists).
507
+ def self.ignore_file_entries_with_empty_notes file
508
+ return [] unless file
509
+
510
+ require 'brakeman/report/ignore/config'
511
+
512
+ config = IgnoreConfig.new(file, nil)
513
+ config.read_from_file
514
+ config.already_ignored_entries_with_empty_notes.map { |i| i[:fingerprint] }
515
+ end
516
+
501
517
  def self.filter_warnings tracker, options
502
518
  require 'brakeman/report/ignore/config'
503
519
 
@@ -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
@@ -160,12 +160,27 @@ class Brakeman::CheckMassAssignment < Brakeman::BaseCheck
160
160
  # Look for and warn about uses of Parameters#permit! for mass assignment
161
161
  def check_permit!
162
162
  tracker.find_call(:method => :permit!, :nested => true).each do |result|
163
- if params? result[:call].target and not result[:chain].include? :slice
164
- 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
165
167
  end
166
168
  end
167
169
  end
168
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
+
169
184
  # Look for actual use of params in mass assignment to avoid
170
185
  # warning about uses of Parameters#permit! without any mass assignment
171
186
  # or when mass assignment is restricted by model instead.
@@ -191,7 +206,7 @@ class Brakeman::CheckMassAssignment < Brakeman::BaseCheck
191
206
  warn :result => result,
192
207
  :warning_type => "Mass Assignment",
193
208
  :warning_code => :mass_assign_permit!,
194
- :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'),
195
210
  :confidence => confidence
196
211
  end
197
212
 
@@ -203,7 +218,7 @@ class Brakeman::CheckMassAssignment < Brakeman::BaseCheck
203
218
  warn :result => result,
204
219
  :warning_type => "Mass Assignment",
205
220
  :warning_code => :mass_assign_permit_all,
206
- :message => "Parameters should be whitelisted for mass assignment",
221
+ :message => msg('Mass assignment is globally enabled. Disable and specify exact keys using ', msg_code('params.permit'), ' instead'),
207
222
  :confidence => :high
208
223
  end
209
224
  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
@@ -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",
@@ -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.
@@ -67,6 +67,10 @@ module Brakeman::Options
67
67
  options[:ensure_latest] = true
68
68
  end
69
69
 
70
+ opts.on "--ensure-ignore-notes", "Fail when an ignored warnings does not include a note" do
71
+ options[:ensure_ignore_notes] = true
72
+ end
73
+
70
74
  opts.on "-3", "--rails3", "Force Rails 3 mode" do
71
75
  options[:rails3] = true
72
76
  end
@@ -82,7 +82,6 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
82
82
  def replace exp, int = 0
83
83
  return exp if int > 3
84
84
 
85
-
86
85
  if replacement = env[exp] and not duplicate? replacement
87
86
  replace(replacement.deep_clone(exp.line), int + 1)
88
87
  elsif tracker and replacement = tracker.constant_lookup(exp) and not duplicate? replacement
@@ -731,14 +730,14 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
731
730
  def array_include_all_literals? exp
732
731
  call? exp and
733
732
  exp.method == :include? and
734
- all_literals? exp.target
733
+ (all_literals? exp.target or dir_glob? exp.target)
735
734
  end
736
735
 
737
736
  def array_detect_all_literals? exp
738
737
  call? exp and
739
738
  [:detect, :find].include? exp.method and
740
739
  exp.first_arg.nil? and
741
- all_literals? exp.target
740
+ (all_literals? exp.target or dir_glob? exp.target)
742
741
  end
743
742
 
744
743
  #Sets @inside_if = true
@@ -20,6 +20,7 @@ class Brakeman::FindAllCalls < Brakeman::BasicProcessor
20
20
  @current_template = opts[:template]
21
21
  @current_file = opts[:file]
22
22
  @current_call = nil
23
+ @full_call = nil
23
24
  process exp
24
25
  end
25
26
 
@@ -137,7 +138,8 @@ class Brakeman::FindAllCalls < Brakeman::BasicProcessor
137
138
  :call => exp,
138
139
  :nested => false,
139
140
  :location => make_location,
140
- :parent => @current_call }.freeze
141
+ :parent => @current_call,
142
+ :full_call => @full_call }.freeze
141
143
  end
142
144
 
143
145
  #Gets the target of a call as a Symbol
@@ -214,34 +216,47 @@ class Brakeman::FindAllCalls < Brakeman::BasicProcessor
214
216
  #Return info hash for a call Sexp
215
217
  def create_call_hash exp
216
218
  target = get_target exp.target
217
-
218
- if call? target or node_type? target, :dxstr # need to index `` even if target of a call
219
- already_in_target = @in_target
220
- @in_target = true
221
- process target
222
- @in_target = already_in_target
223
-
224
- target = get_target(target, :include_calls)
225
- end
219
+ target_symbol = get_target(target, :include_calls)
226
220
 
227
221
  method = exp.method
228
222
 
229
223
  call_hash = {
230
- :target => target,
224
+ :target => target_symbol,
231
225
  :method => method,
232
226
  :call => exp,
233
227
  :nested => @in_target,
234
228
  :chain => get_chain(exp),
235
229
  :location => make_location,
236
- :parent => @current_call
230
+ :parent => @current_call,
231
+ :full_call => @full_call
237
232
  }
238
233
 
234
+ unless @in_target
235
+ @full_call = call_hash
236
+ end
237
+
238
+ # Process up the call chain
239
+ if call? target or node_type? target, :dxstr # need to index `` even if target of a call
240
+ already_in_target = @in_target
241
+ @in_target = true
242
+ process target
243
+ @in_target = already_in_target
244
+ end
245
+
246
+ # Process call arguments
247
+ # but add the current call as the 'parent'
248
+ # to any calls in the arguments
239
249
  old_parent = @current_call
240
250
  @current_call = call_hash
241
251
 
252
+ # Do not set @full_call when processing arguments
253
+ old_full_call = @full_call
254
+ @full_call = nil
255
+
242
256
  process_call_args exp
243
257
 
244
258
  @current_call = old_parent
259
+ @full_call = old_full_call
245
260
 
246
261
  call_hash
247
262
  end
@@ -94,6 +94,10 @@ module Brakeman
94
94
  end
95
95
  end
96
96
 
97
+ def already_ignored_entries_with_empty_notes
98
+ @already_ignored.select { |i| i if i[:note].strip.empty? }
99
+ end
100
+
97
101
  # Read configuration to file
98
102
  def read_from_file file = @file
99
103
  if File.exist? file
@@ -94,11 +94,14 @@ class Brakeman::Scanner
94
94
  #
95
95
  #Stores parsed information in tracker.config
96
96
  def process_config
97
+ # Sometimes folks like to put constants in environment.rb
98
+ # so let's always process it even for newer Rails versions
99
+ process_config_file "environment.rb"
100
+
97
101
  if options[:rails3] or options[:rails4] or options[:rails5] or options[:rails6]
98
102
  process_config_file "application.rb"
99
103
  process_config_file "environments/production.rb"
100
104
  else
101
- process_config_file "environment.rb"
102
105
  process_config_file "gems.rb"
103
106
  end
104
107
 
@@ -198,8 +198,10 @@ class Brakeman::Tracker
198
198
  @constants.add name, value, context unless @options[:disable_constant_tracking]
199
199
  end
200
200
 
201
+ # This method does not return all constants at this time,
202
+ # just ones with "simple" values.
201
203
  def constant_lookup name
202
- @constants.get_literal name unless @options[:disable_constant_tracking]
204
+ @constants.get_simple_value name unless @options[:disable_constant_tracking]
203
205
  end
204
206
 
205
207
  def find_class name
@@ -1,7 +1,10 @@
1
1
  require 'brakeman/processors/output_processor'
2
+ require 'brakeman/util'
2
3
 
3
4
  module Brakeman
4
5
  class Constant
6
+ include Brakeman::Util
7
+
5
8
  attr_reader :name, :name_array, :file, :value, :context
6
9
 
7
10
  def initialize name, value, context = {}
@@ -107,13 +110,11 @@ module Brakeman
107
110
  @constants[base_name] << Constant.new(name, value, context)
108
111
  end
109
112
 
110
- LITERALS = [:lit, :false, :str, :true, :array, :hash]
111
- def literal? exp
112
- exp.is_a? Sexp and LITERALS.include? exp.node_type
113
- end
114
-
115
- def get_literal name
116
- if x = self[name] and literal? x
113
+ # Returns constant values that are not too complicated.
114
+ # Right now that means literal values (string, array, etc.)
115
+ # or calls on Dir.glob(..).whatever.
116
+ def get_simple_value name
117
+ if x = self[name] and (literal? x or dir_glob? x)
117
118
  x
118
119
  else
119
120
  nil
@@ -293,6 +293,22 @@ module Brakeman::Util
293
293
  exp.is_a? Sexp and types.include? exp.node_type
294
294
  end
295
295
 
296
+ LITERALS = [:lit, :false, :str, :true, :array, :hash]
297
+
298
+ def literal? exp
299
+ exp.is_a? Sexp and LITERALS.include? exp.node_type
300
+ end
301
+
302
+ DIR_CONST = s(:const, :Dir)
303
+
304
+ # Dir.glob(...).whatever
305
+ def dir_glob? exp
306
+ exp = exp.block_call if node_type? exp, :iter
307
+ return unless call? exp
308
+
309
+ (exp.target == DIR_CONST and exp.method == :glob) or dir_glob? exp.target
310
+ end
311
+
296
312
  #Returns true if the given _exp_ contains a :class node.
297
313
  #
298
314
  #Useful for checking if a module is just a module or if it is a namespace.
@@ -1,3 +1,3 @@
1
1
  module Brakeman
2
- Version = "4.8.2"
2
+ Version = "4.9.0"
3
3
  end
@@ -117,6 +117,8 @@ module Brakeman::WarningCodes
117
117
  :json_html_escape_config => 113,
118
118
  :json_html_escape_module => 114,
119
119
  :CVE_2020_8159 => 115,
120
+ :CVE_2020_8166 => 116,
121
+ :erb_template_injection => 117,
120
122
 
121
123
  :custom_check => 9090,
122
124
  }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brakeman
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.8.2
4
+ version: 4.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Collins
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-05-12 00:00:00.000000000 Z
11
+ date: 2020-08-04 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Brakeman detects security vulnerabilities in Ruby on Rails applications
14
14
  via static analysis.
@@ -209,48 +209,48 @@ files:
209
209
  - bundle/ruby/2.7.0/gems/safe_yaml-1.0.5/lib/safe_yaml/version.rb
210
210
  - bundle/ruby/2.7.0/gems/safe_yaml-1.0.5/run_specs_all_ruby_versions.sh
211
211
  - bundle/ruby/2.7.0/gems/safe_yaml-1.0.5/safe_yaml.gemspec
212
- - bundle/ruby/2.7.0/gems/sexp_processor-4.14.1/History.rdoc
213
- - bundle/ruby/2.7.0/gems/sexp_processor-4.14.1/Manifest.txt
214
- - bundle/ruby/2.7.0/gems/sexp_processor-4.14.1/README.rdoc
215
- - bundle/ruby/2.7.0/gems/sexp_processor-4.14.1/lib/composite_sexp_processor.rb
216
- - bundle/ruby/2.7.0/gems/sexp_processor-4.14.1/lib/pt_testcase.rb
217
- - bundle/ruby/2.7.0/gems/sexp_processor-4.14.1/lib/sexp.rb
218
- - bundle/ruby/2.7.0/gems/sexp_processor-4.14.1/lib/sexp_matcher.rb
219
- - bundle/ruby/2.7.0/gems/sexp_processor-4.14.1/lib/sexp_processor.rb
220
- - bundle/ruby/2.7.0/gems/sexp_processor-4.14.1/lib/strict_sexp.rb
221
- - bundle/ruby/2.7.0/gems/sexp_processor-4.14.1/lib/unique.rb
222
- - bundle/ruby/2.7.0/gems/slim-4.0.1/CHANGES
223
- - bundle/ruby/2.7.0/gems/slim-4.0.1/Gemfile
224
- - bundle/ruby/2.7.0/gems/slim-4.0.1/LICENSE
225
- - bundle/ruby/2.7.0/gems/slim-4.0.1/README.jp.md
226
- - bundle/ruby/2.7.0/gems/slim-4.0.1/README.md
227
- - bundle/ruby/2.7.0/gems/slim-4.0.1/lib/slim.rb
228
- - bundle/ruby/2.7.0/gems/slim-4.0.1/lib/slim/code_attributes.rb
229
- - bundle/ruby/2.7.0/gems/slim-4.0.1/lib/slim/command.rb
230
- - bundle/ruby/2.7.0/gems/slim-4.0.1/lib/slim/controls.rb
231
- - bundle/ruby/2.7.0/gems/slim-4.0.1/lib/slim/do_inserter.rb
232
- - bundle/ruby/2.7.0/gems/slim-4.0.1/lib/slim/embedded.rb
233
- - bundle/ruby/2.7.0/gems/slim-4.0.1/lib/slim/end_inserter.rb
234
- - bundle/ruby/2.7.0/gems/slim-4.0.1/lib/slim/engine.rb
235
- - bundle/ruby/2.7.0/gems/slim-4.0.1/lib/slim/erb_converter.rb
236
- - bundle/ruby/2.7.0/gems/slim-4.0.1/lib/slim/filter.rb
237
- - bundle/ruby/2.7.0/gems/slim-4.0.1/lib/slim/grammar.rb
238
- - bundle/ruby/2.7.0/gems/slim-4.0.1/lib/slim/include.rb
239
- - bundle/ruby/2.7.0/gems/slim-4.0.1/lib/slim/interpolation.rb
240
- - bundle/ruby/2.7.0/gems/slim-4.0.1/lib/slim/logic_less.rb
241
- - bundle/ruby/2.7.0/gems/slim-4.0.1/lib/slim/logic_less/context.rb
242
- - bundle/ruby/2.7.0/gems/slim-4.0.1/lib/slim/logic_less/filter.rb
243
- - bundle/ruby/2.7.0/gems/slim-4.0.1/lib/slim/parser.rb
244
- - bundle/ruby/2.7.0/gems/slim-4.0.1/lib/slim/smart.rb
245
- - bundle/ruby/2.7.0/gems/slim-4.0.1/lib/slim/smart/escaper.rb
246
- - bundle/ruby/2.7.0/gems/slim-4.0.1/lib/slim/smart/filter.rb
247
- - bundle/ruby/2.7.0/gems/slim-4.0.1/lib/slim/smart/parser.rb
248
- - bundle/ruby/2.7.0/gems/slim-4.0.1/lib/slim/splat/builder.rb
249
- - bundle/ruby/2.7.0/gems/slim-4.0.1/lib/slim/splat/filter.rb
250
- - bundle/ruby/2.7.0/gems/slim-4.0.1/lib/slim/template.rb
251
- - bundle/ruby/2.7.0/gems/slim-4.0.1/lib/slim/translator.rb
252
- - bundle/ruby/2.7.0/gems/slim-4.0.1/lib/slim/version.rb
253
- - bundle/ruby/2.7.0/gems/slim-4.0.1/slim.gemspec
212
+ - bundle/ruby/2.7.0/gems/sexp_processor-4.15.0/History.rdoc
213
+ - bundle/ruby/2.7.0/gems/sexp_processor-4.15.0/Manifest.txt
214
+ - bundle/ruby/2.7.0/gems/sexp_processor-4.15.0/README.rdoc
215
+ - bundle/ruby/2.7.0/gems/sexp_processor-4.15.0/lib/composite_sexp_processor.rb
216
+ - bundle/ruby/2.7.0/gems/sexp_processor-4.15.0/lib/pt_testcase.rb
217
+ - bundle/ruby/2.7.0/gems/sexp_processor-4.15.0/lib/sexp.rb
218
+ - bundle/ruby/2.7.0/gems/sexp_processor-4.15.0/lib/sexp_matcher.rb
219
+ - bundle/ruby/2.7.0/gems/sexp_processor-4.15.0/lib/sexp_processor.rb
220
+ - bundle/ruby/2.7.0/gems/sexp_processor-4.15.0/lib/strict_sexp.rb
221
+ - bundle/ruby/2.7.0/gems/sexp_processor-4.15.0/lib/unique.rb
222
+ - bundle/ruby/2.7.0/gems/slim-4.1.0/CHANGES
223
+ - bundle/ruby/2.7.0/gems/slim-4.1.0/Gemfile
224
+ - bundle/ruby/2.7.0/gems/slim-4.1.0/LICENSE
225
+ - bundle/ruby/2.7.0/gems/slim-4.1.0/README.jp.md
226
+ - bundle/ruby/2.7.0/gems/slim-4.1.0/README.md
227
+ - bundle/ruby/2.7.0/gems/slim-4.1.0/lib/slim.rb
228
+ - bundle/ruby/2.7.0/gems/slim-4.1.0/lib/slim/code_attributes.rb
229
+ - bundle/ruby/2.7.0/gems/slim-4.1.0/lib/slim/command.rb
230
+ - bundle/ruby/2.7.0/gems/slim-4.1.0/lib/slim/controls.rb
231
+ - bundle/ruby/2.7.0/gems/slim-4.1.0/lib/slim/do_inserter.rb
232
+ - bundle/ruby/2.7.0/gems/slim-4.1.0/lib/slim/embedded.rb
233
+ - bundle/ruby/2.7.0/gems/slim-4.1.0/lib/slim/end_inserter.rb
234
+ - bundle/ruby/2.7.0/gems/slim-4.1.0/lib/slim/engine.rb
235
+ - bundle/ruby/2.7.0/gems/slim-4.1.0/lib/slim/erb_converter.rb
236
+ - bundle/ruby/2.7.0/gems/slim-4.1.0/lib/slim/filter.rb
237
+ - bundle/ruby/2.7.0/gems/slim-4.1.0/lib/slim/grammar.rb
238
+ - bundle/ruby/2.7.0/gems/slim-4.1.0/lib/slim/include.rb
239
+ - bundle/ruby/2.7.0/gems/slim-4.1.0/lib/slim/interpolation.rb
240
+ - bundle/ruby/2.7.0/gems/slim-4.1.0/lib/slim/logic_less.rb
241
+ - bundle/ruby/2.7.0/gems/slim-4.1.0/lib/slim/logic_less/context.rb
242
+ - bundle/ruby/2.7.0/gems/slim-4.1.0/lib/slim/logic_less/filter.rb
243
+ - bundle/ruby/2.7.0/gems/slim-4.1.0/lib/slim/parser.rb
244
+ - bundle/ruby/2.7.0/gems/slim-4.1.0/lib/slim/smart.rb
245
+ - bundle/ruby/2.7.0/gems/slim-4.1.0/lib/slim/smart/escaper.rb
246
+ - bundle/ruby/2.7.0/gems/slim-4.1.0/lib/slim/smart/filter.rb
247
+ - bundle/ruby/2.7.0/gems/slim-4.1.0/lib/slim/smart/parser.rb
248
+ - bundle/ruby/2.7.0/gems/slim-4.1.0/lib/slim/splat/builder.rb
249
+ - bundle/ruby/2.7.0/gems/slim-4.1.0/lib/slim/splat/filter.rb
250
+ - bundle/ruby/2.7.0/gems/slim-4.1.0/lib/slim/template.rb
251
+ - bundle/ruby/2.7.0/gems/slim-4.1.0/lib/slim/translator.rb
252
+ - bundle/ruby/2.7.0/gems/slim-4.1.0/lib/slim/version.rb
253
+ - bundle/ruby/2.7.0/gems/slim-4.1.0/slim.gemspec
254
254
  - bundle/ruby/2.7.0/gems/temple-0.8.2/CHANGES
255
255
  - bundle/ruby/2.7.0/gems/temple-0.8.2/EXPRESSIONS.md
256
256
  - bundle/ruby/2.7.0/gems/temple-0.8.2/Gemfile
@@ -381,6 +381,7 @@ files:
381
381
  - lib/brakeman/checks/check_cookie_serialization.rb
382
382
  - lib/brakeman/checks/check_create_with.rb
383
383
  - lib/brakeman/checks/check_cross_site_scripting.rb
384
+ - lib/brakeman/checks/check_csrf_token_forgery_cve.rb
384
385
  - lib/brakeman/checks/check_default_routes.rb
385
386
  - lib/brakeman/checks/check_deserialize.rb
386
387
  - lib/brakeman/checks/check_detailed_exceptions.rb
@@ -442,6 +443,7 @@ files:
442
443
  - lib/brakeman/checks/check_strip_tags.rb
443
444
  - lib/brakeman/checks/check_symbol_dos.rb
444
445
  - lib/brakeman/checks/check_symbol_dos_cve.rb
446
+ - lib/brakeman/checks/check_template_injection.rb
445
447
  - lib/brakeman/checks/check_translate_bug.rb
446
448
  - lib/brakeman/checks/check_unsafe_reflection.rb
447
449
  - lib/brakeman/checks/check_unscoped_find.rb