brakeman-lib 3.3.2 → 3.3.3

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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +13 -0
  3. data/lib/brakeman/app_tree.rb +6 -1
  4. data/lib/brakeman/checks/base_check.rb +10 -0
  5. data/lib/brakeman/checks/check_create_with.rb +1 -2
  6. data/lib/brakeman/checks/check_cross_site_scripting.rb +0 -4
  7. data/lib/brakeman/checks/check_deserialize.rb +1 -2
  8. data/lib/brakeman/checks/check_dynamic_finders.rb +1 -2
  9. data/lib/brakeman/checks/check_evaluation.rb +1 -2
  10. data/lib/brakeman/checks/check_execute.rb +2 -5
  11. data/lib/brakeman/checks/check_file_access.rb +1 -2
  12. data/lib/brakeman/checks/check_link_to_href.rb +13 -3
  13. data/lib/brakeman/checks/check_mass_assignment.rb +2 -4
  14. data/lib/brakeman/checks/check_redirect.rb +1 -4
  15. data/lib/brakeman/checks/check_regex_dos.rb +1 -2
  16. data/lib/brakeman/checks/check_render.rb +10 -5
  17. data/lib/brakeman/checks/check_render_inline.rb +1 -2
  18. data/lib/brakeman/checks/check_select_tag.rb +1 -2
  19. data/lib/brakeman/checks/check_send.rb +1 -2
  20. data/lib/brakeman/checks/check_session_manipulation.rb +1 -2
  21. data/lib/brakeman/checks/check_simple_format.rb +1 -2
  22. data/lib/brakeman/checks/check_ssl_verify.rb +1 -2
  23. data/lib/brakeman/checks/check_symbol_dos.rb +2 -4
  24. data/lib/brakeman/checks/check_unsafe_reflection.rb +1 -2
  25. data/lib/brakeman/checks/check_weak_hash.rb +3 -6
  26. data/lib/brakeman/parsers/template_parser.rb +9 -0
  27. data/lib/brakeman/processors/base_processor.rb +25 -0
  28. data/lib/brakeman/processors/controller_processor.rb +6 -99
  29. data/lib/brakeman/processors/erb_template_processor.rb +1 -4
  30. data/lib/brakeman/processors/erubis_template_processor.rb +4 -16
  31. data/lib/brakeman/processors/haml_template_processor.rb +4 -11
  32. data/lib/brakeman/processors/lib/find_all_calls.rb +13 -25
  33. data/lib/brakeman/processors/lib/find_return_value.rb +34 -4
  34. data/lib/brakeman/processors/lib/module_helper.rb +111 -0
  35. data/lib/brakeman/processors/lib/render_helper.rb +1 -1
  36. data/lib/brakeman/processors/library_processor.rb +4 -57
  37. data/lib/brakeman/processors/model_processor.rb +4 -104
  38. data/lib/brakeman/processors/slim_template_processor.rb +7 -21
  39. data/lib/brakeman/processors/template_processor.rb +11 -0
  40. data/lib/brakeman/scanner.rb +1 -1
  41. data/lib/brakeman/version.rb +1 -1
  42. data/lib/ruby_parser/bm_sexp.rb +7 -3
  43. metadata +4 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 247e1f6cbd985e4c43a49652500d38319984d212
4
- data.tar.gz: bb49ccd6dce05cab284eca01935d2368a7c976e3
3
+ metadata.gz: e4f086cc0f5c5aa7d689faf4145c49801f21457f
4
+ data.tar.gz: 6ab7f7fed14040fc66d6973b70147b25cf48f959
5
5
  SHA512:
6
- metadata.gz: f213baa263336bc6589ae552d87d10fb498abefc4b1921b6a3056abd80716910a61a1c5cedae8c2ec5317f1bcb8fb391cc9832cd6ffbfe014d3dcd4de3bb00c6
7
- data.tar.gz: 9b8b4242889b5c03f59c0dec5a21e98bef3dcbdfe3a05cf8f5ac8ae1a9c826f60418cc1b5b9ab3c5c823be3c616da9922fa4511a64a4b48bf149c1917114a418
6
+ metadata.gz: e08d73e3e686eb091e925d425fd16426b10784cffc6bcc67135c296c60e6c02cdcdedde92ba536846dc4d01182d9c8071cc64b8f57c7615e671d8062d5fae901
7
+ data.tar.gz: b92eed67245b493cfc3bab3f11068bc97983784dea1cc4b0616a0c833d5121015547e513ea9f51fa177693a75ccf0c2180fb1c2d0ec5c78e76dd7646a2fe426d
data/CHANGES CHANGED
@@ -1,3 +1,16 @@
1
+ # 3.3.3
2
+
3
+ * Show path when no Rails app found (Neil Matatall)
4
+ * Index calls in view helpers
5
+ * Process inline template renders
6
+ * Avoid warning about hashes in link_to hrefs
7
+ * Add documentation for authentication category
8
+ * Ignore boolean methods in render paths
9
+ * Reduce open redirect duplicates
10
+ * Fix SymbolDoS error with unknown Rails version
11
+ * Sexp#value returns nil when there is no value
12
+ * Improve return value estimation
13
+
1
14
  # 3.3.2
2
15
 
3
16
  * Fix serious performance regression with global constant tracking
@@ -106,11 +106,16 @@ module Brakeman
106
106
 
107
107
  def lib_paths
108
108
  @lib_files ||= find_paths("lib").reject { |path| path.include? "/generators/" or path.include? "lib/tasks/" } +
109
- find_additional_lib_paths
109
+ find_additional_lib_paths +
110
+ find_helper_paths
110
111
  end
111
112
 
112
113
  private
113
114
 
115
+ def find_helper_paths
116
+ find_paths "app/helpers"
117
+ end
118
+
114
119
  def find_additional_lib_paths
115
120
  @additional_libs_path.collect{ |path| find_paths path }.flatten
116
121
  end
@@ -131,6 +131,10 @@ class Brakeman::BaseCheck < Brakeman::SexpProcessor
131
131
  @comparison_ops.include? meth
132
132
  end
133
133
 
134
+ def boolean_method? method
135
+ method[-1] == "?"
136
+ end
137
+
134
138
  #Report a warning
135
139
  def warn options
136
140
  extra_opts = { :check => self.class.to_s }
@@ -233,6 +237,12 @@ class Brakeman::BaseCheck < Brakeman::SexpProcessor
233
237
  @mass_assign_disabled
234
238
  end
235
239
 
240
+ def original? result
241
+ return false if result[:call].original_line or duplicate? result
242
+ add_result result
243
+ true
244
+ end
245
+
236
246
  #This is to avoid reporting duplicates. Checks if the result has been
237
247
  #reported already from the same line number.
238
248
  def duplicate? result, location = nil
@@ -26,8 +26,7 @@ class Brakeman::CheckCreateWith < Brakeman::BaseCheck
26
26
  end
27
27
 
28
28
  def process_result result
29
- return if duplicate? result
30
- add_result result
29
+ return unless original? result
31
30
  arg = result[:call].first_arg
32
31
 
33
32
  confidence = danger_level arg
@@ -378,8 +378,4 @@ class Brakeman::CheckCrossSiteScripting < Brakeman::BaseCheck
378
378
  def safe_input_attribute? target, method
379
379
  target and always_safe_method? method
380
380
  end
381
-
382
- def boolean_method? method
383
- method.to_s.end_with? "?"
384
- end
385
381
  end
@@ -30,8 +30,7 @@ class Brakeman::CheckDeserialize < Brakeman::BaseCheck
30
30
  end
31
31
 
32
32
  def check_deserialize result, target, arg = nil
33
- return if duplicate? result
34
- add_result result
33
+ return unless original? result
35
34
 
36
35
  arg ||= result[:call].first_arg
37
36
  method = result[:call].method
@@ -15,8 +15,7 @@ class Brakeman::CheckDynamicFinders < Brakeman::BaseCheck
15
15
  end
16
16
 
17
17
  def process_result result
18
- return if duplicate? result or result[:call].original_line
19
- add_result result
18
+ return unless original? result
20
19
 
21
20
  call = result[:call]
22
21
 
@@ -20,8 +20,7 @@ class Brakeman::CheckEvaluation < Brakeman::BaseCheck
20
20
 
21
21
  #Warns if eval includes user input
22
22
  def process_result result
23
- return if duplicate? result or result[:call].original_line
24
- add_result result
23
+ return unless original? result
25
24
 
26
25
  if input = include_user_input?(result[:call].arglist)
27
26
  warn :result => result,
@@ -53,8 +53,7 @@ class Brakeman::CheckExecute < Brakeman::BaseCheck
53
53
  failure = include_user_input?(args) || dangerous_interp?(args)
54
54
  end
55
55
 
56
- if failure and not duplicate? result
57
- add_result result
56
+ if failure and original? result
58
57
 
59
58
  if failure.type == :interp #Not from user input
60
59
  confidence = CONFIDENCE[:med]
@@ -107,9 +106,7 @@ class Brakeman::CheckExecute < Brakeman::BaseCheck
107
106
 
108
107
  #Processes backticks.
109
108
  def process_backticks result
110
- return if duplicate? result
111
-
112
- add_result result
109
+ return unless original? result
113
110
 
114
111
  exp = result[:call]
115
112
 
@@ -27,8 +27,7 @@ class Brakeman::CheckFileAccess < Brakeman::BaseCheck
27
27
  end
28
28
 
29
29
  def process_result result
30
- return if duplicate? result
31
- add_result result
30
+ return unless original? result
32
31
  call = result[:call]
33
32
  file_name = call.first_arg
34
33
 
@@ -17,7 +17,7 @@ class Brakeman::CheckLinkToHref < Brakeman::CheckLinkTo
17
17
  :hidden_field, :hidden_field_tag, :image_tag, :label,
18
18
  :mail_to, :polymorphic_url, :radio_button, :select, :slice,
19
19
  :submit_tag, :text_area, :text_field,
20
- :text_field_tag, :url_encode, :u, :url_for,
20
+ :text_field_tag, :url_encode, :u,
21
21
  :will_paginate].merge(tracker.options[:url_safe_methods] || [])
22
22
 
23
23
  @models = tracker.models.keys
@@ -36,6 +36,10 @@ class Brakeman::CheckLinkToHref < Brakeman::CheckLinkTo
36
36
  @matched = false
37
37
  url_arg = process call.second_arg
38
38
 
39
+ if call? url_arg and url_arg.method == :url_for
40
+ url_arg = url_arg.first_arg
41
+ end
42
+
39
43
  #Ignore situations where the href is an interpolated string
40
44
  #with something before the user input
41
45
  return if string_interp?(url_arg) && !url_arg[1].chomp.empty?
@@ -45,7 +49,7 @@ class Brakeman::CheckLinkToHref < Brakeman::CheckLinkTo
45
49
  if input = has_immediate_user_input?(url_arg)
46
50
  message = "Unsafe #{friendly_type_of input} in link_to href"
47
51
 
48
- unless duplicate? result
52
+ unless duplicate? result or call_on_params? url_arg
49
53
  add_result result
50
54
  warn :result => result,
51
55
  :warning_type => "Cross Site Scripting",
@@ -74,7 +78,7 @@ class Brakeman::CheckLinkToHref < Brakeman::CheckLinkTo
74
78
  elsif @matched
75
79
  if @matched.type == :model and not tracker.options[:ignore_model_output]
76
80
  message = "Unsafe model attribute in link_to href"
77
- elsif @matched.type == :params
81
+ elsif @matched.type == :params and not call_on_params? @matched.match
78
82
  message = "Unsafe parameter value in link_to href"
79
83
  end
80
84
 
@@ -112,4 +116,10 @@ class Brakeman::CheckLinkToHref < Brakeman::CheckLinkTo
112
116
  MODEL_METHODS.include? exp.method or
113
117
  exp.method.to_s =~ /^find_by_/
114
118
  end
119
+
120
+ def call_on_params? exp
121
+ call? exp and
122
+ params? exp.target and
123
+ exp.method != :[]
124
+ end
115
125
  end
@@ -65,8 +65,7 @@ class Brakeman::CheckMassAssignment < Brakeman::BaseCheck
65
65
 
66
66
  check = check_call call
67
67
 
68
- if check and not call.original_line and not duplicate? res
69
- add_result res
68
+ if check and original? res
70
69
 
71
70
  model = tracker.models[res[:chain].first]
72
71
 
@@ -180,8 +179,7 @@ class Brakeman::CheckMassAssignment < Brakeman::BaseCheck
180
179
  end
181
180
 
182
181
  def warn_on_permit! result
183
- return if duplicate? result or result[:call].original_line
184
- add_result result
182
+ return unless original? result
185
183
 
186
184
  confidence = if subsequent_mass_assignment? result
187
185
  CONFIDENCE[:high]
@@ -29,10 +29,9 @@ class Brakeman::CheckRedirect < Brakeman::BaseCheck
29
29
  end
30
30
 
31
31
  def process_result result
32
- return if duplicate? result
32
+ return unless original? result
33
33
 
34
34
  call = result[:call]
35
-
36
35
  method = call.method
37
36
 
38
37
  if method == :redirect_to and
@@ -41,8 +40,6 @@ class Brakeman::CheckRedirect < Brakeman::BaseCheck
41
40
  not slice_call?(call.first_arg) and
42
41
  res = include_user_input?(call)
43
42
 
44
- add_result result
45
-
46
43
  if res.type == :immediate
47
44
  confidence = CONFIDENCE[:high]
48
45
  else
@@ -26,8 +26,7 @@ class Brakeman::CheckRegexDoS < Brakeman::BaseCheck
26
26
 
27
27
  #Warns if regex includes user input
28
28
  def process_result result
29
- return if duplicate? result or result[:call].original_line
30
- add_result result
29
+ return unless original? result
31
30
 
32
31
  call = result[:call]
33
32
  components = call[1..-1]
@@ -32,8 +32,7 @@ class Brakeman::CheckRender < Brakeman::BaseCheck
32
32
  def check_for_dynamic_path result
33
33
  view = result[:call][2]
34
34
 
35
- if sexp? view and not duplicate? result
36
- add_result result
35
+ if sexp? view and original? result
37
36
 
38
37
  if input = has_immediate_user_input?(view)
39
38
  if string_interp? view
@@ -84,9 +83,15 @@ class Brakeman::CheckRender < Brakeman::BaseCheck
84
83
  end
85
84
 
86
85
  def safe_param? exp
87
- if params? exp and call? exp and exp.method == :[]
88
- arg = exp.first_arg
89
- symbol? arg and [:controller, :action].include? arg.value
86
+ if params? exp and call? exp
87
+ method_name = exp.method
88
+
89
+ if method_name == :[]
90
+ arg = exp.first_arg
91
+ symbol? arg and [:controller, :action].include? arg.value
92
+ else
93
+ boolean_method? method_name
94
+ end
90
95
  end
91
96
  end
92
97
  end
@@ -12,8 +12,7 @@ class Brakeman::CheckRenderInline < Brakeman::CheckCrossSiteScripting
12
12
  end
13
13
 
14
14
  def check_render result
15
- return if duplicate? result
16
- add_result result
15
+ return unless original? result
17
16
 
18
17
  call = result[:call]
19
18
 
@@ -34,8 +34,7 @@ class Brakeman::CheckSelectTag < Brakeman::BaseCheck
34
34
 
35
35
  #Check if select_tag is called with user input in :prompt option
36
36
  def process_result result
37
- return if duplicate? result
38
- add_result result
37
+ return unless original? result
39
38
 
40
39
  #Only concerned if user input is supplied for :prompt option
41
40
  last_arg = result[:call].last_arg
@@ -17,8 +17,7 @@ class Brakeman::CheckSend < Brakeman::BaseCheck
17
17
  end
18
18
 
19
19
  def process_result result
20
- return if duplicate? result or result[:call].original_line
21
- add_result result
20
+ return unless original? result
22
21
 
23
22
  send_call = get_send result[:call]
24
23
  process_call_args send_call
@@ -12,8 +12,7 @@ class Brakeman::CheckSessionManipulation < Brakeman::BaseCheck
12
12
  end
13
13
 
14
14
  def process_result result
15
- return if duplicate? result or result[:call].original_line
16
- add_result result
15
+ return unless original? result
17
16
 
18
17
  index = result[:call].first_arg
19
18
 
@@ -43,8 +43,7 @@ class Brakeman::CheckSimpleFormat < Brakeman::CheckCrossSiteScripting
43
43
  end
44
44
 
45
45
  def warn_on_simple_format result, match
46
- return if duplicate? result
47
- add_result result
46
+ return unless original? result
48
47
 
49
48
  @found_any = true
50
49
 
@@ -37,8 +37,7 @@ class Brakeman::CheckSSLVerify < Brakeman::BaseCheck
37
37
  end
38
38
 
39
39
  def warn_about_ssl_verification_bypass result
40
- return if duplicate?(result)
41
- add_result result
40
+ return unless original? result
42
41
 
43
42
  warn :result => result,
44
43
  :warning_type => "SSL Verification Bypass",
@@ -8,7 +8,7 @@ class Brakeman::CheckSymbolDoS < Brakeman::BaseCheck
8
8
  @description = "Checks for symbol denial of service"
9
9
 
10
10
  def run_check
11
- return if rails_version > "5.0.0"
11
+ return if rails_version and rails_version > "5.0.0"
12
12
 
13
13
  tracker.find_call(:methods => UNSAFE_METHODS, :nested => true).each do |result|
14
14
  check_unsafe_symbol_creation(result)
@@ -16,9 +16,7 @@ class Brakeman::CheckSymbolDoS < Brakeman::BaseCheck
16
16
  end
17
17
 
18
18
  def check_unsafe_symbol_creation result
19
- return if duplicate? result or result[:call].original_line
20
-
21
- add_result result
19
+ return unless original? result
22
20
 
23
21
  call = result[:call]
24
22
 
@@ -18,8 +18,7 @@ class Brakeman::CheckUnsafeReflection < Brakeman::BaseCheck
18
18
  end
19
19
 
20
20
  def check_unsafe_reflection result
21
- return if duplicate? result or result[:call].original_line
22
- add_result result
21
+ return unless original? result
23
22
 
24
23
  call = result[:call]
25
24
  method = call.method
@@ -22,8 +22,7 @@ class Brakeman::CheckWeakHash < Brakeman::BaseCheck
22
22
  end
23
23
 
24
24
  def process_hash_result result
25
- return if duplicate? result
26
- add_result result
25
+ return unless original? result
27
26
 
28
27
  input = nil
29
28
  call = result[:call]
@@ -59,8 +58,7 @@ class Brakeman::CheckWeakHash < Brakeman::BaseCheck
59
58
  end
60
59
 
61
60
  def process_hmac_result result
62
- return if duplicate? result
63
- add_result result
61
+ return unless original? result
64
62
 
65
63
  call = result[:call]
66
64
 
@@ -81,8 +79,7 @@ class Brakeman::CheckWeakHash < Brakeman::BaseCheck
81
79
  end
82
80
 
83
81
  def process_openssl_result result
84
- return if duplicate? result
85
- add_result result
82
+ return unless original? result
86
83
 
87
84
  arg = result[:call].first_arg
88
85
 
@@ -85,5 +85,14 @@ module Brakeman
85
85
  Slim::Template.new(:disable_capture => true,
86
86
  :generator => Temple::Generators::RailsOutputBuffer) { text }.precompiled_template
87
87
  end
88
+
89
+ def self.parse_inline_erb tracker, text
90
+ fp = Brakeman::FileParser.new(nil, nil)
91
+ tp = self.new(tracker, fp)
92
+ src = tp.parse_erb text
93
+ type = tp.erubis? ? :erubis : :erb
94
+
95
+ return type, fp.parse_ruby(src, "_inline_")
96
+ end
88
97
  end
89
98
  end
@@ -272,6 +272,31 @@ class Brakeman::BaseProcessor < Brakeman::SexpProcessor
272
272
 
273
273
  type ||= :default
274
274
  value ||= :default
275
+
276
+ if type == :inline and string? value and not hash_access(rest, :type)
277
+ value, rest = make_inline_render(value, rest)
278
+ end
279
+
275
280
  return type, value, rest
276
281
  end
282
+
283
+ def make_inline_render value, options
284
+ require 'brakeman/parsers/template_parser'
285
+
286
+ class_or_module = (@current_class || @current_module)
287
+
288
+ class_or_module = if class_or_module.nil?
289
+ "Unknown"
290
+ else
291
+ class_or_module.name
292
+ end
293
+
294
+ template_name = "#@current_method/inline@#{value.line}:#{class_or_module}".to_sym
295
+ type, ast = Brakeman::TemplateParser.parse_inline_erb(@tracker, value.value)
296
+ ast = ast.deep_clone(value.line)
297
+ @tracker.processor.process_template(template_name, ast, type, nil, @file_name)
298
+ @tracker.processor.process_template_alias(@tracker.templates[template_name])
299
+
300
+ return s(:lit, template_name), options
301
+ end
277
302
  end