brakeman 3.3.2 → 3.3.3

Sign up to get free protection for your applications and to get access to all the features.
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: e8c028effaee5449ceb9ae4536b57db115597cbf
4
- data.tar.gz: 49b860b6cee1fcadbda293659fb55b816650c4b5
3
+ metadata.gz: 08318cd38973d83265973cfcaffb09907d92bc25
4
+ data.tar.gz: f147beaa68bf28730c008478c98e666480d58ada
5
5
  SHA512:
6
- metadata.gz: 53a61c3720d15d802b4904606cb08bd9e07e075360bdbbeb6e97afce32316d76ab0d5e87d3d336f514ef46f4cfebcc4fd68388b3e7cf9f4c9d0680a20f0a584a
7
- data.tar.gz: 7cb28661d7a0a012e348475c5a74a69ba4d9c28077b66489d0f2b6507a19628bd0220244a1fa87bfd3abb4cea5e707aacbd71f3790ebffc78e57ca7a3374cc4a
6
+ metadata.gz: d7fd63e6289c6019accc98f91b5a8d6d10d610d8b5829a73641a89930097b80979a5143c8c5688662dbc367532d3d62cc68dbc6352322a66decce9d76e4f8570
7
+ data.tar.gz: 46bd51e6d4b76c8d8d0120cc9932bd0987800b03e0b2eb7eff7d97c127a88811d8859bdfc6dbb6d00bcc05d112b1d6b4fdb69e175b171293b5a1b11cee4c2f25
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