brakeman-lib 4.4.0 → 4.7.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 (97) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +63 -0
  3. data/README.md +6 -7
  4. data/lib/brakeman.rb +7 -0
  5. data/lib/brakeman/app_tree.rb +34 -22
  6. data/lib/brakeman/call_index.rb +54 -15
  7. data/lib/brakeman/checks.rb +7 -7
  8. data/lib/brakeman/checks/base_check.rb +75 -56
  9. data/lib/brakeman/checks/check_content_tag.rb +12 -0
  10. data/lib/brakeman/checks/check_cookie_serialization.rb +22 -0
  11. data/lib/brakeman/checks/check_cross_site_scripting.rb +15 -10
  12. data/lib/brakeman/checks/check_default_routes.rb +5 -0
  13. data/lib/brakeman/checks/check_deserialize.rb +49 -0
  14. data/lib/brakeman/checks/check_dynamic_finders.rb +1 -1
  15. data/lib/brakeman/checks/check_evaluation.rb +0 -1
  16. data/lib/brakeman/checks/check_execute.rb +44 -1
  17. data/lib/brakeman/checks/check_file_access.rb +7 -1
  18. data/lib/brakeman/checks/check_force_ssl.rb +27 -0
  19. data/lib/brakeman/checks/check_header_dos.rb +2 -2
  20. data/lib/brakeman/checks/check_i18n_xss.rb +2 -2
  21. data/lib/brakeman/checks/check_jruby_xml.rb +2 -2
  22. data/lib/brakeman/checks/check_json_parsing.rb +7 -2
  23. data/lib/brakeman/checks/check_link_to_href.rb +6 -1
  24. data/lib/brakeman/checks/check_mail_to.rb +1 -1
  25. data/lib/brakeman/checks/check_mime_type_dos.rb +2 -2
  26. data/lib/brakeman/checks/check_model_attr_accessible.rb +1 -1
  27. data/lib/brakeman/checks/check_model_attributes.rb +12 -50
  28. data/lib/brakeman/checks/check_model_serialize.rb +1 -1
  29. data/lib/brakeman/checks/check_nested_attributes_bypass.rb +4 -4
  30. data/lib/brakeman/checks/check_reverse_tabnabbing.rb +54 -0
  31. data/lib/brakeman/checks/check_sanitize_methods.rb +2 -2
  32. data/lib/brakeman/checks/check_secrets.rb +1 -1
  33. data/lib/brakeman/checks/check_send.rb +0 -1
  34. data/lib/brakeman/checks/check_session_manipulation.rb +0 -1
  35. data/lib/brakeman/checks/check_session_settings.rb +15 -12
  36. data/lib/brakeman/checks/check_simple_format.rb +5 -0
  37. data/lib/brakeman/checks/check_skip_before_filter.rb +1 -1
  38. data/lib/brakeman/checks/check_sql.rb +27 -20
  39. data/lib/brakeman/checks/check_validation_regex.rb +1 -1
  40. data/lib/brakeman/checks/check_xml_dos.rb +2 -2
  41. data/lib/brakeman/checks/check_yaml_parsing.rb +10 -18
  42. data/lib/brakeman/differ.rb +16 -28
  43. data/lib/brakeman/file_parser.rb +6 -8
  44. data/lib/brakeman/file_path.rb +85 -0
  45. data/lib/brakeman/options.rb +7 -0
  46. data/lib/brakeman/parsers/haml_embedded.rb +44 -0
  47. data/lib/brakeman/parsers/slim_embedded.rb +44 -0
  48. data/lib/brakeman/parsers/template_parser.rb +8 -8
  49. data/lib/brakeman/processor.rb +4 -5
  50. data/lib/brakeman/processors/alias_processor.rb +49 -7
  51. data/lib/brakeman/processors/base_processor.rb +10 -7
  52. data/lib/brakeman/processors/controller_alias_processor.rb +10 -7
  53. data/lib/brakeman/processors/controller_processor.rb +9 -13
  54. data/lib/brakeman/processors/gem_processor.rb +10 -2
  55. data/lib/brakeman/processors/haml_template_processor.rb +92 -123
  56. data/lib/brakeman/processors/lib/call_conversion_helper.rb +4 -0
  57. data/lib/brakeman/processors/lib/find_all_calls.rb +27 -4
  58. data/lib/brakeman/processors/lib/find_call.rb +3 -64
  59. data/lib/brakeman/processors/lib/module_helper.rb +8 -8
  60. data/lib/brakeman/processors/lib/processor_helper.rb +3 -3
  61. data/lib/brakeman/processors/lib/rails2_config_processor.rb +4 -4
  62. data/lib/brakeman/processors/lib/rails2_route_processor.rb +2 -2
  63. data/lib/brakeman/processors/lib/rails3_config_processor.rb +3 -3
  64. data/lib/brakeman/processors/lib/rails3_route_processor.rb +2 -2
  65. data/lib/brakeman/processors/lib/render_helper.rb +2 -2
  66. data/lib/brakeman/processors/lib/render_path.rb +18 -1
  67. data/lib/brakeman/processors/library_processor.rb +5 -5
  68. data/lib/brakeman/processors/model_processor.rb +4 -5
  69. data/lib/brakeman/processors/output_processor.rb +5 -0
  70. data/lib/brakeman/processors/slim_template_processor.rb +16 -0
  71. data/lib/brakeman/processors/template_alias_processor.rb +32 -5
  72. data/lib/brakeman/processors/template_processor.rb +14 -10
  73. data/lib/brakeman/report.rb +3 -3
  74. data/lib/brakeman/report/ignore/config.rb +2 -3
  75. data/lib/brakeman/report/ignore/interactive.rb +2 -2
  76. data/lib/brakeman/report/pager.rb +1 -0
  77. data/lib/brakeman/report/report_base.rb +51 -6
  78. data/lib/brakeman/report/report_codeclimate.rb +3 -3
  79. data/lib/brakeman/report/report_hash.rb +1 -1
  80. data/lib/brakeman/report/report_html.rb +2 -2
  81. data/lib/brakeman/report/report_json.rb +1 -24
  82. data/lib/brakeman/report/report_table.rb +20 -4
  83. data/lib/brakeman/report/report_tabs.rb +1 -1
  84. data/lib/brakeman/report/report_text.rb +2 -2
  85. data/lib/brakeman/rescanner.rb +13 -12
  86. data/lib/brakeman/scanner.rb +24 -18
  87. data/lib/brakeman/tracker.rb +35 -7
  88. data/lib/brakeman/tracker/collection.rb +4 -3
  89. data/lib/brakeman/tracker/config.rb +44 -48
  90. data/lib/brakeman/tracker/constants.rb +2 -1
  91. data/lib/brakeman/util.rb +18 -147
  92. data/lib/brakeman/version.rb +1 -1
  93. data/lib/brakeman/warning.rb +27 -13
  94. data/lib/brakeman/warning_codes.rb +4 -0
  95. data/lib/ruby_parser/bm_sexp.rb +1 -1
  96. data/lib/ruby_parser/bm_sexp_processor.rb +1 -0
  97. metadata +58 -43
@@ -54,7 +54,7 @@ class Brakeman::CheckModelSerialize < Brakeman::BaseCheck
54
54
  confidence = :high
55
55
  end
56
56
 
57
- warn :model => model.name,
57
+ warn :model => model,
58
58
  :warning_type => "Remote Code Execution",
59
59
  :warning_code => :CVE_2013_0277,
60
60
  :message => msg("Serialized attributes are vulnerable in ", msg_version(rails_version), ", upgrade to ", msg_version(@upgrade_version), " or patch"),
@@ -22,17 +22,17 @@ class Brakeman::CheckNestedAttributesBypass < Brakeman::BaseCheck
22
22
  if opts = model.options[:accepts_nested_attributes_for]
23
23
  opts.each do |args|
24
24
  if args.any? { |a| allow_destroy? a } and args.any? { |a| reject_if? a }
25
- warn_about_nested_attributes name, model, args
25
+ warn_about_nested_attributes model, args
26
26
  end
27
27
  end
28
28
  end
29
29
  end
30
30
  end
31
31
 
32
- def warn_about_nested_attributes name, model, args
32
+ def warn_about_nested_attributes model, args
33
33
  message = msg(msg_version(rails_version), " does not call ", msg_code(":reject_if"), " option when ", msg_code(":allow_destroy"), " is ", msg_code("false"), " ", msg_cve("CVE-2015-7577"))
34
34
 
35
- warn :model => name,
35
+ warn :model => model,
36
36
  :warning_type => "Nested Attributes",
37
37
  :warning_code => :CVE_2015_7577,
38
38
  :message => message,
@@ -53,6 +53,6 @@ class Brakeman::CheckNestedAttributesBypass < Brakeman::BaseCheck
53
53
  end
54
54
 
55
55
  def workaround?
56
- tracker.check_initializers([], :will_be_destroyed?).any?
56
+ tracker.find_call(method: :will_be_destroyed?).any?
57
57
  end
58
58
  end
@@ -0,0 +1,54 @@
1
+ require 'brakeman/checks/base_check'
2
+
3
+ class Brakeman::CheckReverseTabnabbing < Brakeman::BaseCheck
4
+ Brakeman::Checks.add_optional self
5
+
6
+ @description = "Checks for reverse tabnabbing cases on 'link_to' calls"
7
+
8
+ def run_check
9
+ calls = tracker.find_call :methods => :link_to
10
+ calls.each do |call|
11
+ process_result call
12
+ end
13
+ end
14
+
15
+ def process_result result
16
+ return unless original? result and result[:call].last_arg
17
+
18
+ html_opts = result[:call].last_arg
19
+ return unless hash? html_opts
20
+
21
+ target = hash_access html_opts, :target
22
+ return unless target && string?(target) && target.value == "_blank"
23
+
24
+ target_url = result[:block] ? result[:call].first_arg : result[:call].second_arg
25
+
26
+ # `url_for` and `_path` calls lead to urls on to the same origin.
27
+ # That means that an adversary would need to run javascript on
28
+ # the victim application's domain. If that is the case, the adversary
29
+ # already has the ability to redirect the victim user anywhere.
30
+ # Also statically provided URLs (interpolated or otherwise) are also
31
+ # ignored as they produce many false positives.
32
+ return if !call?(target_url) || target_url.method.match(/^url_for$|_path$/)
33
+
34
+ rel = hash_access html_opts, :rel
35
+ confidence = :medium
36
+
37
+ if rel && string?(rel) then
38
+ rel_opt = rel.value
39
+ return if rel_opt.include?("noopener") && rel_opt.include?("noreferrer")
40
+
41
+ if rel_opt.include?("noopener") ^ rel_opt.include?("noreferrer") then
42
+ confidence = :weak
43
+ end
44
+ end
45
+
46
+ warn :result => result,
47
+ :warning_type => "Reverse Tabnabbing",
48
+ :warning_code => :reverse_tabnabbing,
49
+ :message => msg("When opening a link in a new tab without setting ", msg_code('rel: "noopener noreferrer"'),
50
+ ", the new tab can control the parent tab's location. For example, an attacker could redirect to a phishing page."),
51
+ :confidence => confidence,
52
+ :user_input => rel
53
+ end
54
+ end
@@ -70,7 +70,7 @@ class Brakeman::CheckSanitizeMethods < Brakeman::BaseCheck
70
70
 
71
71
  def check_cve_2018_8048
72
72
  if loofah_vulnerable_cve_2018_8048?
73
- message = msg(msg_version(tracker.config.gem_version(:loofah), "loofah gem"), " is vulnerable (CVE-2018-8048). Upgrade to 2.1.2")
73
+ message = msg(msg_version(tracker.config.gem_version(:loofah), "loofah gem"), " is vulnerable (CVE-2018-8048). Upgrade to 2.2.1")
74
74
 
75
75
  if tracker.find_call(:target => false, :method => :sanitize).any?
76
76
  confidence = :high
@@ -90,7 +90,7 @@ 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.1.2"
93
+ loofah_version and loofah_version < "2.2.1"
94
94
  end
95
95
 
96
96
  def warn_sanitizer_cve cve, link, upgrade_version
@@ -35,6 +35,6 @@ class Brakeman::CheckSecrets < Brakeman::BaseCheck
35
35
 
36
36
  def looks_like_secret? name
37
37
  # REST_AUTH_SITE_KEY is the pepper in Devise
38
- name.match /password|secret|(rest_auth_site|api)_key$/i
38
+ name.match(/password|secret|(rest_auth_site|api)_key$/i)
39
39
  end
40
40
  end
@@ -28,7 +28,6 @@ class Brakeman::CheckSend < Brakeman::BaseCheck
28
28
  :warning_type => "Dangerous Send",
29
29
  :warning_code => :dangerous_send,
30
30
  :message => "User controlled method execution",
31
- :code => result[:call],
32
31
  :user_input => input,
33
32
  :confidence => :high
34
33
  end
@@ -27,7 +27,6 @@ class Brakeman::CheckSessionManipulation < Brakeman::BaseCheck
27
27
  :warning_type => "Session Manipulation",
28
28
  :warning_code => :session_key_manipulation,
29
29
  :message => msg(msg_input(input), " used as key in session hash"),
30
- :code => result[:call],
31
30
  :user_input => input,
32
31
  :confidence => confidence
33
32
  end
@@ -19,10 +19,13 @@ class Brakeman::CheckSessionSettings < Brakeman::BaseCheck
19
19
  def run_check
20
20
  settings = tracker.config.session_settings
21
21
 
22
- check_for_issues settings, @app_tree.expand_path("config/environment.rb")
22
+ check_for_issues settings, @app_tree.file_path("config/environment.rb")
23
23
 
24
- ["session_store.rb", "secret_token.rb"].each do |file|
25
- if tracker.initializers[file] and not ignored? file
24
+ session_store = @app_tree.file_path("config/initializers/session_store.rb")
25
+ secret_token = @app_tree.file_path("config/initializers/secret_token.rb")
26
+
27
+ [session_store, secret_token].each do |file|
28
+ if tracker.initializers[file] and not ignored? file.basename
26
29
  process tracker.initializers[file]
27
30
  end
28
31
  end
@@ -42,13 +45,13 @@ class Brakeman::CheckSessionSettings < Brakeman::BaseCheck
42
45
  #in Rails 4.x apps
43
46
  def process_attrasgn exp
44
47
  if not tracker.options[:rails3] and exp.target == @session_settings and exp.method == :session=
45
- check_for_issues exp.first_arg, @app_tree.expand_path("config/initializers/session_store.rb")
48
+ check_for_issues exp.first_arg, @app_tree.file_path("config/initializers/session_store.rb")
46
49
  end
47
50
 
48
51
  if tracker.options[:rails3] and settings_target?(exp.target) and
49
52
  (exp.method == :secret_token= or exp.method == :secret_key_base=) and string? exp.first_arg
50
53
 
51
- warn_about_secret_token exp.line, @app_tree.expand_path("config/initializers/secret_token.rb")
54
+ warn_about_secret_token exp.line, @app_tree.file_path("config/initializers/secret_token.rb")
52
55
  end
53
56
 
54
57
  exp
@@ -58,7 +61,7 @@ class Brakeman::CheckSessionSettings < Brakeman::BaseCheck
58
61
  #in Rails 3.x apps
59
62
  def process_call exp
60
63
  if tracker.options[:rails3] and settings_target?(exp.target) and exp.method == :session_store
61
- check_for_rails3_issues exp.second_arg, @app_tree.expand_path("config/initializers/session_store.rb")
64
+ check_for_rails3_issues exp.second_arg, @app_tree.file_path("config/initializers/session_store.rb")
62
65
  end
63
66
 
64
67
  exp
@@ -109,10 +112,10 @@ class Brakeman::CheckSessionSettings < Brakeman::BaseCheck
109
112
  end
110
113
 
111
114
  def check_secrets_yaml
112
- secrets_file = "config/secrets.yml"
115
+ secrets_file = @app_tree.file_path("config/secrets.yml")
113
116
 
114
- if @app_tree.exists? secrets_file and not ignored? "secrets.yml" and not ignored? "config/*.yml"
115
- yaml = @app_tree.read secrets_file
117
+ if secrets_file.exists? and not ignored? "secrets.yml" and not ignored? "config/*.yml"
118
+ yaml = secrets_file.read
116
119
  require 'date' # https://github.com/dtao/safe_yaml/issues/80
117
120
  require 'safe_yaml/load'
118
121
  begin
@@ -127,7 +130,7 @@ class Brakeman::CheckSessionSettings < Brakeman::BaseCheck
127
130
  unless secret.include? "<%="
128
131
  line = yaml.lines.find_index { |l| l.include? secret } + 1
129
132
 
130
- warn_about_secret_token line, @app_tree.expand_path(secrets_file)
133
+ warn_about_secret_token line, @app_tree.file_path(secrets_file)
131
134
  end
132
135
  end
133
136
  end
@@ -163,9 +166,9 @@ class Brakeman::CheckSessionSettings < Brakeman::BaseCheck
163
166
 
164
167
  def ignored? file
165
168
  [".", "config", "config/initializers"].each do |dir|
166
- ignore_file = "#{dir}/.gitignore"
169
+ ignore_file = @app_tree.file_path("#{dir}/.gitignore")
167
170
  if @app_tree.exists? ignore_file
168
- input = @app_tree.read(ignore_file)
171
+ input = ignore_file.read
169
172
 
170
173
  return true if input.include? file
171
174
  end
@@ -5,6 +5,11 @@ class Brakeman::CheckSimpleFormat < Brakeman::CheckCrossSiteScripting
5
5
 
6
6
  @description = "Checks for simple_format XSS vulnerability (CVE-2013-6416) in certain versions"
7
7
 
8
+ def initialize *args
9
+ super
10
+ @found_any = false
11
+ end
12
+
8
13
  def run_check
9
14
  if version_between? "4.0.0", "4.0.1"
10
15
  @inspect_arguments = true
@@ -38,7 +38,7 @@ class Brakeman::CheckSkipBeforeFilter < Brakeman::BaseCheck
38
38
  :message => msg("Use whitelist (", msg_code(":only => [..]"), ") when skipping authentication"),
39
39
  :code => filter,
40
40
  :confidence => :medium,
41
- :link => "authentication_whitelist",
41
+ :link_path => "authentication_whitelist",
42
42
  :file => controller.file
43
43
  end
44
44
  end
@@ -14,12 +14,15 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
14
14
  @description = "Check for SQL injection"
15
15
 
16
16
  def run_check
17
- narrow_targets = [:exists?, :select]
17
+ # Avoid reporting `user_input` on silly values when generating warning.
18
+ # Note that we retroactively find `user_input` inside the "dangerous" value.
19
+ @safe_input_attributes.merge IGNORE_METHODS_IN_SQL
18
20
 
19
21
  @sql_targets = [:average, :calculate, :count, :count_by_sql, :delete_all, :destroy_all,
20
22
  :find_by_sql, :maximum, :minimum, :pluck, :sum, :update_all]
21
23
  @sql_targets.concat [:from, :group, :having, :joins, :lock, :order, :reorder, :where] if tracker.options[:rails3]
22
- @sql_targets << :find_by << :find_by! << :not if tracker.options[:rails4]
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]
23
26
 
24
27
  if version_between?("2.0.0", "3.9.9") or tracker.config.rails_version.nil?
25
28
  @sql_targets << :first << :last << :all
@@ -43,6 +46,7 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
43
46
  Brakeman.debug "Finding possible SQL calls on models"
44
47
  calls = tracker.find_call(:methods => @sql_targets, :nested => true)
45
48
 
49
+ narrow_targets = [:exists?, :select]
46
50
  calls.concat tracker.find_call(:targets => active_record_models.keys, :methods => narrow_targets, :chained => true)
47
51
 
48
52
  Brakeman.debug "Finding possible SQL calls with no target"
@@ -68,23 +72,23 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
68
72
  scope_calls = []
69
73
 
70
74
  if version_between?("2.1.0", "3.0.9")
71
- ar_scope_calls(:named_scope) do |name, args|
75
+ ar_scope_calls(:named_scope) do |model, args|
72
76
  call = make_call(nil, :named_scope, args).line(args.line)
73
- scope_calls << scope_call_hash(call, name, :named_scope)
77
+ scope_calls << scope_call_hash(call, model, :named_scope)
74
78
  end
75
79
  elsif version_between?("3.1.0", "9.9.9")
76
- ar_scope_calls(:scope) do |name, args|
80
+ ar_scope_calls(:scope) do |model, args|
77
81
  second_arg = args[2]
78
82
  next unless sexp? second_arg
79
83
 
80
84
  if second_arg.node_type == :iter and node_type? second_arg.block, :block, :call, :safe_call
81
- process_scope_with_block(name, args)
85
+ process_scope_with_block(model, args)
82
86
  elsif call? second_arg
83
87
  call = second_arg
84
- scope_calls << scope_call_hash(call, name, call.method)
88
+ scope_calls << scope_call_hash(call, model, call.method)
85
89
  else
86
90
  call = make_call(nil, :scope, args).line(args.line)
87
- scope_calls << scope_call_hash(call, name, :scope)
91
+ scope_calls << scope_call_hash(call, model, :scope)
88
92
  end
89
93
  end
90
94
  end
@@ -93,37 +97,34 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
93
97
  end
94
98
 
95
99
  def ar_scope_calls(symbol_name = :named_scope, &block)
96
- return_array = []
97
100
  active_record_models.each do |name, model|
98
101
  model_args = model.options[symbol_name]
99
102
  if model_args
100
103
  model_args.each do |args|
101
- yield name, args
102
- return_array << [name, args]
104
+ yield model, args
103
105
  end
104
106
  end
105
107
  end
106
- return_array
107
108
  end
108
109
 
109
- def scope_call_hash(call, name, method)
110
- { :call => call, :location => { :type => :class, :class => name }, :method => :named_scope }
110
+ def scope_call_hash(call, model, method)
111
+ { :call => call, :location => { :type => :class, :class => model.name, :file => model.file }, :method => :named_scope }
111
112
  end
112
113
 
113
114
 
114
- def process_scope_with_block model_name, args
115
+ def process_scope_with_block model, args
115
116
  scope_name = args[1][1]
116
117
  block = args[-1][-1]
117
118
 
118
119
  # Search lambda for calls to query methods
119
120
  if block.node_type == :block
120
121
  find_calls = Brakeman::FindAllCalls.new(tracker)
121
- find_calls.process_source(block, :class => model_name, :method => scope_name)
122
+ find_calls.process_source(block, :class => model.name, :method => scope_name, :file => model.file)
122
123
  find_calls.calls.each { |call| process_result(call) if @sql_targets.include?(call[:method]) }
123
124
  elsif call? block
124
125
  while call? block
125
126
  process_result :target => block.target, :method => block.method, :call => block,
126
- :location => { :type => :class, :class => model_name, :method => scope_name }
127
+ :location => { :type => :class, :class => model.name, :method => scope_name, :file => model.file }
127
128
 
128
129
  block = block.target
129
130
  end
@@ -184,7 +185,7 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
184
185
  else
185
186
  check_find_arguments call.last_arg
186
187
  end
187
- when :where, :having, :find_by, :find_by!, :not
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
188
189
  check_query_arguments call.arglist
189
190
  when :order, :group, :reorder
190
191
  check_order_arguments call.arglist
@@ -294,7 +295,7 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
294
295
  # Model.where(params[:where])
295
296
  arg
296
297
  end
297
- elsif hash? arg
298
+ elsif hash? arg and not kwsplat? arg
298
299
  #This is generally going to be a hash of column names and values, which
299
300
  #would escape the values. But the keys _could_ be user input.
300
301
  check_hash_keys arg
@@ -452,7 +453,13 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
452
453
  when :dstr
453
454
  check_string_interp exp
454
455
  when :hash
455
- check_hash_values exp unless ignore_hash
456
+ if kwsplat? exp and has_immediate_user_input? exp
457
+ exp
458
+ elsif not ignore_hash
459
+ check_hash_values exp
460
+ else
461
+ nil
462
+ end
456
463
  when :if
457
464
  unsafe_sql? exp.then_clause or unsafe_sql? exp.else_clause
458
465
  when :call
@@ -17,7 +17,7 @@ class Brakeman::CheckValidationRegex < Brakeman::BaseCheck
17
17
 
18
18
  def run_check
19
19
  active_record_models.each do |name, model|
20
- @current_model = name
20
+ @current_model = model
21
21
  format_validations = model.options[:validates_format_of]
22
22
 
23
23
  if format_validations
@@ -34,8 +34,8 @@ class Brakeman::CheckXMLDoS < Brakeman::BaseCheck
34
34
  end
35
35
 
36
36
  def has_workaround?
37
- tracker.check_initializers(:"ActiveSupport::XmlMini", :backend=).any? do |match|
38
- arg = match.call.first_arg
37
+ tracker.find_call(target: :"ActiveSupport::XmlMini", method: :backend=).any? do |match|
38
+ arg = match[:call].first_arg
39
39
  if string? arg
40
40
  value = arg.value
41
41
  value == 'Nokogiri' or value == 'LibXML'
@@ -48,21 +48,17 @@ class Brakeman::CheckYAMLParsing < Brakeman::BaseCheck
48
48
  def disabled_xml_parser?
49
49
  if version_between? "0.0.0", "2.3.14"
50
50
  #Look for ActionController::Base.param_parsers.delete(Mime::XML)
51
- params_parser = s(:call,
52
- s(:colon2, s(:const, :ActionController), :Base),
53
- :param_parsers)
54
-
55
- matches = tracker.check_initializers(params_parser, :delete)
51
+ matches = tracker.find_call(target: :"ActionController::Base.param_parsers", method: :delete)
56
52
  else
57
53
  #Look for ActionDispatch::ParamsParser::DEFAULT_PARSERS.delete(Mime::XML)
58
- matches = tracker.check_initializers(:"ActionDispatch::ParamsParser::DEFAULT_PARSERS", :delete)
54
+ matches = tracker.find_call(target: :"ActionDispatch::ParamsParser::DEFAULT_PARSERS", method: :delete)
59
55
  end
60
56
 
61
57
  unless matches.empty?
62
58
  mime_xml = s(:colon2, s(:const, :Mime), :XML)
63
59
 
64
60
  matches.each do |result|
65
- if result.call.first_arg == mime_xml
61
+ if result[:call].first_arg == mime_xml
66
62
  return true
67
63
  end
68
64
  end
@@ -74,18 +70,14 @@ class Brakeman::CheckYAMLParsing < Brakeman::BaseCheck
74
70
  #Look for ActionController::Base.param_parsers[Mime::YAML] = :yaml
75
71
  #in Rails 2.x apps
76
72
  def enabled_yaml_parser?
77
- param_parsers = s(:call,
78
- s(:colon2, s(:const, :ActionController), :Base),
79
- :param_parsers)
80
-
81
- matches = tracker.check_initializers(param_parsers, :[]=)
73
+ matches = tracker.find_call(target: :'ActionController::Base.param_parsers', method: :[]=)
82
74
 
83
75
  mime_yaml = s(:colon2, s(:const, :Mime), :YAML)
84
76
 
85
77
  matches.each do |result|
86
- if result.call.first_arg == mime_yaml and
87
- symbol? result.call.second_arg and
88
- result.call.second_arg.value == :yaml
78
+ if result[:call].first_arg == mime_yaml and
79
+ symbol? result[:call].second_arg and
80
+ result[:call].second_arg.value == :yaml
89
81
 
90
82
  return true
91
83
  end
@@ -96,16 +88,16 @@ class Brakeman::CheckYAMLParsing < Brakeman::BaseCheck
96
88
 
97
89
  def disabled_xml_dangerous_types?
98
90
  if version_between? "0.0.0", "2.3.14"
99
- matches = tracker.check_initializers(:"ActiveSupport::CoreExtensions::Hash::Conversions::XML_PARSING", :delete)
91
+ matches = tracker.find_call(target: :"ActiveSupport::CoreExtensions::Hash::Conversions::XML_PARSING", method: :delete)
100
92
  else
101
- matches = tracker.check_initializers(:"ActiveSupport::XmlMini::PARSING", :delete)
93
+ matches = tracker.find_call(target: :"ActiveSupport::XmlMini::PARSING", method: :delete)
102
94
  end
103
95
 
104
96
  symbols_off = false
105
97
  yaml_off = false
106
98
 
107
99
  matches.each do |result|
108
- arg = result.call.first_arg
100
+ arg = result[:call].first_arg
109
101
 
110
102
  if string? arg
111
103
  if arg.value == "yaml"