brakeman 1.8.3 → 1.9.0.pre1

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 (63) hide show
  1. data/README.md +3 -27
  2. data/lib/brakeman.rb +36 -38
  3. data/lib/brakeman/app_tree.rb +90 -0
  4. data/lib/brakeman/call_index.rb +5 -38
  5. data/lib/brakeman/checks.rb +11 -11
  6. data/lib/brakeman/checks/base_check.rb +53 -29
  7. data/lib/brakeman/checks/check_cross_site_scripting.rb +11 -9
  8. data/lib/brakeman/checks/check_evaluation.rb +1 -1
  9. data/lib/brakeman/checks/check_execute.rb +3 -3
  10. data/lib/brakeman/checks/check_link_to.rb +15 -13
  11. data/lib/brakeman/checks/check_link_to_href.rb +1 -1
  12. data/lib/brakeman/checks/check_mail_to.rb +1 -1
  13. data/lib/brakeman/checks/check_mass_assignment.rb +27 -13
  14. data/lib/brakeman/checks/check_redirect.rb +4 -4
  15. data/lib/brakeman/checks/check_select_tag.rb +1 -1
  16. data/lib/brakeman/checks/check_select_vulnerability.rb +1 -1
  17. data/lib/brakeman/checks/check_send.rb +2 -2
  18. data/lib/brakeman/checks/check_session_settings.rb +12 -5
  19. data/lib/brakeman/checks/check_single_quotes.rb +3 -3
  20. data/lib/brakeman/checks/check_skip_before_filter.rb +4 -3
  21. data/lib/brakeman/checks/check_sql.rb +30 -30
  22. data/lib/brakeman/checks/check_translate_bug.rb +11 -10
  23. data/lib/brakeman/checks/check_validation_regex.rb +36 -11
  24. data/lib/brakeman/checks/check_without_protection.rb +1 -1
  25. data/lib/brakeman/options.rb +6 -2
  26. data/lib/brakeman/processor.rb +6 -5
  27. data/lib/brakeman/processors/alias_processor.rb +153 -38
  28. data/lib/brakeman/processors/base_processor.rb +16 -21
  29. data/lib/brakeman/processors/controller_alias_processor.rb +24 -11
  30. data/lib/brakeman/processors/controller_processor.rb +25 -25
  31. data/lib/brakeman/processors/erb_template_processor.rb +6 -7
  32. data/lib/brakeman/processors/erubis_template_processor.rb +2 -3
  33. data/lib/brakeman/processors/gem_processor.rb +5 -4
  34. data/lib/brakeman/processors/haml_template_processor.rb +4 -6
  35. data/lib/brakeman/processors/lib/find_all_calls.rb +3 -3
  36. data/lib/brakeman/processors/lib/find_call.rb +2 -2
  37. data/lib/brakeman/processors/lib/find_return_value.rb +134 -0
  38. data/lib/brakeman/processors/lib/processor_helper.rb +24 -2
  39. data/lib/brakeman/processors/lib/rails2_config_processor.rb +13 -14
  40. data/lib/brakeman/processors/lib/rails2_route_processor.rb +9 -4
  41. data/lib/brakeman/processors/lib/rails3_config_processor.rb +8 -8
  42. data/lib/brakeman/processors/lib/rails3_route_processor.rb +23 -21
  43. data/lib/brakeman/processors/lib/render_helper.rb +2 -2
  44. data/lib/brakeman/processors/library_processor.rb +2 -2
  45. data/lib/brakeman/processors/model_processor.rb +16 -12
  46. data/lib/brakeman/processors/output_processor.rb +2 -1
  47. data/lib/brakeman/processors/template_alias_processor.rb +12 -8
  48. data/lib/brakeman/report.rb +28 -14
  49. data/lib/brakeman/rescanner.rb +5 -5
  50. data/lib/brakeman/scanner.rb +56 -94
  51. data/lib/brakeman/templates/header.html.erb +7 -2
  52. data/lib/brakeman/tracker.rb +14 -4
  53. data/lib/brakeman/util.rb +38 -17
  54. data/lib/brakeman/version.rb +1 -1
  55. data/lib/brakeman/warning.rb +14 -6
  56. data/lib/ruby_parser/bm_sexp.rb +157 -57
  57. data/lib/ruby_parser/bm_sexp_processor.rb +1 -2
  58. metadata +26 -25
  59. data/lib/ruby_parser/ruby18_parser.rb +0 -5544
  60. data/lib/ruby_parser/ruby19_parser.rb +0 -5756
  61. data/lib/ruby_parser/ruby_lexer.rb +0 -1349
  62. data/lib/ruby_parser/ruby_parser.rb +0 -5
  63. data/lib/ruby_parser/ruby_parser_extras.rb +0 -1057
@@ -69,7 +69,7 @@ class Brakeman::FindCall < Brakeman::BaseProcessor
69
69
 
70
70
  #Process body of method
71
71
  def process_methdef exp
72
- process exp.body
72
+ process_all exp.body
73
73
  end
74
74
 
75
75
  alias :process_selfdef :process_methdef
@@ -84,7 +84,7 @@ class Brakeman::FindCall < Brakeman::BaseProcessor
84
84
  target = get_target exp.target
85
85
  method = exp.method
86
86
 
87
- process_all exp.args
87
+ process_call_args exp
88
88
 
89
89
  if match(@find_targets, target) and match(@find_methods, method)
90
90
 
@@ -0,0 +1,134 @@
1
+ require 'brakeman/processors/alias_processor'
2
+
3
+ #Attempts to determine the return value of a method.
4
+ #
5
+ #Preferred usage:
6
+ #
7
+ # Brakeman::FindReturnValue.return_value exp
8
+ class Brakeman::FindReturnValue
9
+ include Brakeman::Util
10
+
11
+ #Returns a guess at the return value of a given method or other block of code.
12
+ #
13
+ #If multiple return values are possible, returns all values in an :or Sexp.
14
+ def self.return_value exp, env = nil
15
+ self.new.get_return_value exp, env
16
+ end
17
+
18
+ def initialize
19
+ @uses_ivars = false
20
+ @return_values = []
21
+ end
22
+
23
+ def uses_ivars?
24
+ @uses_ivars
25
+ end
26
+
27
+ #Find return value of Sexp. Takes an optional starting environment.
28
+ def get_return_value exp, env = nil
29
+ process_method exp, env
30
+ value = make_return_value
31
+ value.original_line(exp.line)
32
+ value
33
+ end
34
+
35
+ #Process method (or, actually, any Sexp) for return value.
36
+ def process_method exp, env = nil
37
+ exp = Brakeman::AliasProcessor.new.process_safely exp, env
38
+
39
+ find_explicit_return_values exp
40
+
41
+ if node_type? exp, :methdef, :selfdef, :defn, :defs
42
+ body = exp.body
43
+
44
+ unless body.empty?
45
+ @return_values << last_value(body)
46
+ else
47
+ Brakeman.debug "FindReturnValue: Empty method? #{exp.inspect}"
48
+ end
49
+ elsif exp
50
+ @return_values << last_value(exp)
51
+ else
52
+ Brakeman.debug "FindReturnValue: Given something strange? #{exp.inspect}"
53
+ end
54
+
55
+ exp
56
+ end
57
+
58
+ #Searches expression for return statements.
59
+ def find_explicit_return_values exp
60
+ todo = [exp]
61
+
62
+ until todo.empty?
63
+ current = todo.shift
64
+
65
+ @uses_ivars = true if node_type? current, :ivar
66
+
67
+ if node_type? current, :return
68
+ @return_values << current.value unless current.value.nil?
69
+ elsif sexp? current
70
+ todo = current[1..-1].concat todo
71
+ end
72
+ end
73
+ end
74
+
75
+ #Determines the "last value" of an expression.
76
+ def last_value exp
77
+ case exp.node_type
78
+ when :rlist, :block, :scope, Sexp
79
+ last_value exp.last
80
+ when :if
81
+ then_clause = exp.then_clause
82
+ else_clause = exp.else_clause
83
+
84
+ if then_clause.nil?
85
+ last_value else_clause
86
+ elsif else_clause.nil?
87
+ last_value then_clause
88
+ else
89
+ true_branch = last_value then_clause
90
+ false_branch = last_value else_clause
91
+
92
+ if true_branch and false_branch
93
+ value = make_or(true_branch, false_branch)
94
+ value.original_line(value.rhs.line)
95
+ value
96
+ else #Unlikely?
97
+ true_branch or false_branch
98
+ end
99
+ end
100
+ when :lasgn, :iasgn
101
+ exp.rhs
102
+ when :return
103
+ exp.value
104
+ else
105
+ exp.original_line(exp.line) unless exp.original_line
106
+ exp
107
+ end
108
+ end
109
+
110
+ def make_or lhs, rhs
111
+ #Better checks in future
112
+ if lhs == rhs
113
+ lhs
114
+ else
115
+ Sexp.new(:or, lhs, rhs)
116
+ end
117
+ end
118
+
119
+ #Turns the array of return values into an :or Sexp
120
+ def make_return_value
121
+ @return_values.compact!
122
+ @return_values.uniq!
123
+
124
+ if @return_values.empty?
125
+ Sexp.new(:nil)
126
+ elsif @return_values.length == 1
127
+ @return_values.first
128
+ else
129
+ @return_values.reduce do |value, sexp|
130
+ make_or value, sexp
131
+ end
132
+ end
133
+ end
134
+ end
@@ -7,6 +7,28 @@ module Brakeman::ProcessorHelper
7
7
  exp
8
8
  end
9
9
 
10
+ def process_all! exp
11
+ exp.map! do |e|
12
+ if sexp? e
13
+ process e
14
+ else
15
+ e
16
+ end
17
+ end
18
+
19
+ exp
20
+ end
21
+
22
+ #Process the arguments of a method call. Does not store results.
23
+ #
24
+ #This method is used because Sexp#args and Sexp#arglist create new objects.
25
+ def process_call_args exp
26
+ exp.each_arg do |a|
27
+ process a if sexp? a
28
+ end
29
+
30
+ exp
31
+ end
10
32
  #Sets the current module.
11
33
  def process_module exp
12
34
  module_name = class_name(exp.class_name).to_s
@@ -18,7 +40,7 @@ module Brakeman::ProcessorHelper
18
40
  @current_module = module_name
19
41
  end
20
42
 
21
- process exp.body
43
+ process_all exp.body
22
44
 
23
45
  @current_module = prev_module
24
46
 
@@ -35,7 +57,7 @@ module Brakeman::ProcessorHelper
35
57
  when :lvar
36
58
  exp.value.to_sym
37
59
  when :colon2
38
- "#{class_name(exp[1])}::#{exp[2]}".to_sym
60
+ "#{class_name(exp.lhs)}::#{exp.rhs}".to_sym
39
61
  when :colon3
40
62
  "::#{exp.value}".to_sym
41
63
  when :call
@@ -1,10 +1,3 @@
1
- #Replace block variable in
2
- #
3
- # Rails::Initializer.run |config|
4
- #
5
- #with this value so we can keep track of it.
6
- Brakeman::RAILS_CONFIG = Sexp.new(:const, :"!BRAKEMAN_RAILS_CONFIG") unless defined? Brakeman::RAILS_CONFIG
7
-
8
1
  #Processes configuration. Results are put in tracker.config.
9
2
  #
10
3
  #Configuration of Rails via Rails::Initializer are stored in tracker.config[:rails].
@@ -20,6 +13,13 @@ Brakeman::RAILS_CONFIG = Sexp.new(:const, :"!BRAKEMAN_RAILS_CONFIG") unless defi
20
13
  #
21
14
  #Values for tracker.config[:rails] will still be Sexps.
22
15
  class Brakeman::Rails2ConfigProcessor < Brakeman::BaseProcessor
16
+ #Replace block variable in
17
+ #
18
+ # Rails::Initializer.run |config|
19
+ #
20
+ #with this value so we can keep track of it.
21
+ RAILS_CONFIG = Sexp.new(:const, :"!BRAKEMAN_RAILS_CONFIG")
22
+
23
23
  def initialize *args
24
24
  super
25
25
  @tracker.config[:rails] ||= {}
@@ -46,7 +46,7 @@ class Brakeman::Rails2ConfigProcessor < Brakeman::BaseProcessor
46
46
 
47
47
  #Look for configuration settings
48
48
  def process_attrasgn exp
49
- if exp.target == Brakeman::RAILS_CONFIG
49
+ if exp.target == RAILS_CONFIG
50
50
  #Get rid of '=' at end
51
51
  attribute = exp.method.to_s[0..-2].to_sym
52
52
  if exp.args.length > 1
@@ -83,12 +83,12 @@ class Brakeman::Rails2ConfigProcessor < Brakeman::BaseProcessor
83
83
  def include_rails_config? exp
84
84
  target = exp.target
85
85
  if call? target
86
- if target.target == Brakeman::RAILS_CONFIG
86
+ if target.target == RAILS_CONFIG
87
87
  true
88
88
  else
89
89
  include_rails_config? target
90
90
  end
91
- elsif target == Brakeman::RAILS_CONFIG
91
+ elsif target == RAILS_CONFIG
92
92
  true
93
93
  else
94
94
  false
@@ -107,7 +107,7 @@ class Brakeman::Rails2ConfigProcessor < Brakeman::BaseProcessor
107
107
  attribute = exp.method.to_s[0..-2].to_sym
108
108
  get_rails_config(exp.target) << attribute
109
109
  elsif call? exp
110
- if exp.target == Brakeman::RAILS_CONFIG
110
+ if exp.target == RAILS_CONFIG
111
111
  [exp.method]
112
112
  else
113
113
  get_rails_config(exp.target) << exp.method
@@ -129,14 +129,13 @@ class Brakeman::ConfigAliasProcessor < Brakeman::AliasProcessor
129
129
  # ...
130
130
  # end
131
131
  #
132
- #and replace config with Brakeman::RAILS_CONFIG
132
+ #and replace config with RAILS_CONFIG
133
133
  def process_iter exp
134
134
  target = exp.block_call.target
135
135
  method = exp.block_call.method
136
136
 
137
-
138
137
  if sexp? target and target == RAILS_INIT and method == :run
139
- exp.block_args.rhs = Brakeman::RAILS_CONFIG
138
+ env[Sexp.new(:lvar, exp.block_args.value)] = Brakeman::Rails2ConfigProcessor::RAILS_CONFIG
140
139
  end
141
140
 
142
141
  process_default exp
@@ -200,7 +200,12 @@ class Brakeman::Rails2RoutesProcessor < Brakeman::BaseProcessor
200
200
 
201
201
  exp.last.each_with_index do |e,i|
202
202
  if symbol? e and e.value == :action
203
- @tracker.routes[@current_controller] << exp.last[i + 1].value.to_sym
203
+ action = exp.last[i + 1]
204
+
205
+ if node_type? action, :lit
206
+ @tracker.routes[@current_controller] << action.value.to_sym
207
+ end
208
+
204
209
  return
205
210
  end
206
211
  end
@@ -210,8 +215,8 @@ class Brakeman::Rails2RoutesProcessor < Brakeman::BaseProcessor
210
215
  # something.resources :blah
211
216
  # end
212
217
  def process_with_options exp
213
- @with_options = exp.block_call.args.last
214
- @nested = Sexp.new(:lvar, exp.block_args.lhs)
218
+ @with_options = exp.block_call.last_arg
219
+ @nested = Sexp.new(:lvar, exp.block_args.value)
215
220
 
216
221
  self.current_controller = check_for_controller_name exp.block_call.args
217
222
 
@@ -233,7 +238,7 @@ class Brakeman::Rails2RoutesProcessor < Brakeman::BaseProcessor
233
238
  @prefix << camelize(call.first_arg.value)
234
239
 
235
240
  if formal_args
236
- @nested = Sexp.new(:lvar, formal_args.lhs)
241
+ @nested = Sexp.new(:lvar, formal_args.value)
237
242
  end
238
243
 
239
244
  process block
@@ -1,5 +1,3 @@
1
- Brakeman::RAILS_CONFIG = Sexp.new(:call, nil, :config, Sexp.new(:arglist))
2
-
3
1
  #Processes configuration. Results are put in tracker.config.
4
2
  #
5
3
  #Configuration of Rails via Rails::Initializer are stored in tracker.config[:rails].
@@ -15,6 +13,8 @@ Brakeman::RAILS_CONFIG = Sexp.new(:call, nil, :config, Sexp.new(:arglist))
15
13
  #
16
14
  #Values for tracker.config[:rails] will still be Sexps.
17
15
  class Brakeman::Rails3ConfigProcessor < Brakeman::BaseProcessor
16
+ RAILS_CONFIG = Sexp.new(:call, nil, :config)
17
+
18
18
  def initialize *args
19
19
  super
20
20
  @tracker.config[:rails] ||= {}
@@ -31,7 +31,7 @@ class Brakeman::Rails3ConfigProcessor < Brakeman::BaseProcessor
31
31
  def process_iter exp
32
32
  if node_type?(exp.block_call.target, :colon2) and exp.block_call.method == :Application
33
33
  @inside_config = true
34
- process exp.body if sexp? exp.body
34
+ process_all exp.body if sexp? exp.body
35
35
  @inside_config = false
36
36
  end
37
37
 
@@ -42,7 +42,7 @@ class Brakeman::Rails3ConfigProcessor < Brakeman::BaseProcessor
42
42
  def process_class exp
43
43
  if exp.class_name == :Application
44
44
  @inside_config = true
45
- process exp.body if sexp? exp.body
45
+ process_all exp.body if sexp? exp.body
46
46
  @inside_config = false
47
47
  end
48
48
 
@@ -53,7 +53,7 @@ class Brakeman::Rails3ConfigProcessor < Brakeman::BaseProcessor
53
53
  def process_attrasgn exp
54
54
  return exp unless @inside_config
55
55
 
56
- if exp.target == Brakeman::RAILS_CONFIG
56
+ if exp.target == RAILS_CONFIG
57
57
  #Get rid of '=' at end
58
58
  attribute = exp.method.to_s[0..-2].to_sym
59
59
  if exp.args.length > 1
@@ -80,12 +80,12 @@ class Brakeman::Rails3ConfigProcessor < Brakeman::BaseProcessor
80
80
  def include_rails_config? exp
81
81
  target = exp.target
82
82
  if call? target
83
- if target.target == Brakeman::RAILS_CONFIG
83
+ if target.target == RAILS_CONFIG
84
84
  true
85
85
  else
86
86
  include_rails_config? target
87
87
  end
88
- elsif target == Brakeman::RAILS_CONFIG
88
+ elsif target == RAILS_CONFIG
89
89
  true
90
90
  else
91
91
  false
@@ -104,7 +104,7 @@ class Brakeman::Rails3ConfigProcessor < Brakeman::BaseProcessor
104
104
  attribute = exp.method.to_s[0..-2].to_sym
105
105
  get_rails_config(exp.target) << attribute
106
106
  elsif call? exp
107
- if exp.target == Brakeman::RAILS_CONFIG
107
+ if exp.target == RAILS_CONFIG
108
108
  [exp.method]
109
109
  else
110
110
  get_rails_config(exp.target) << exp.method
@@ -72,9 +72,7 @@ class Brakeman::Rails3RoutesProcessor < Brakeman::BaseProcessor
72
72
 
73
73
  #TODO: Need test for this
74
74
  def process_root exp
75
- args = exp.args
76
-
77
- if value = hash_access(args.first, :to)
75
+ if value = hash_access(exp.first_arg, :to)
78
76
  if string? value
79
77
  add_route_from_string value
80
78
  end
@@ -84,27 +82,29 @@ class Brakeman::Rails3RoutesProcessor < Brakeman::BaseProcessor
84
82
  end
85
83
 
86
84
  def process_match exp
87
- args = exp.args
85
+ first_arg = exp.first_arg
86
+ second_arg = exp.second_arg
87
+ last_arg = exp.last_arg
88
88
 
89
89
  #Check if there is an unrestricted action parameter
90
90
  action_variable = false
91
91
 
92
- if string? args.first
93
- matcher = args.first.value
92
+ if string? first_arg
93
+ matcher = first_arg.value
94
94
 
95
95
  if matcher == ':controller(/:action(/:id(.:format)))' or
96
96
  matcher.include? ':controller' and matcher.include? ':action' #Default routes
97
- @tracker.routes[:allow_all_actions] = args.first
97
+ @tracker.routes[:allow_all_actions] = first_arg
98
98
  return exp
99
99
  elsif matcher.include? ':action'
100
100
  action_variable = true
101
- elsif args[1].nil? and in_controller_block? and not matcher.include? ":"
101
+ elsif second_arg.nil? and in_controller_block? and not matcher.include? ":"
102
102
  add_route matcher
103
103
  end
104
104
  end
105
105
 
106
- if hash? args.last
107
- hash_iterate args.last do |k, v|
106
+ if hash? last_arg
107
+ hash_iterate last_arg do |k, v|
108
108
  if string? k
109
109
  if string? v
110
110
  add_route_from_string v
@@ -153,13 +153,13 @@ class Brakeman::Rails3RoutesProcessor < Brakeman::BaseProcessor
153
153
  end
154
154
 
155
155
  def process_verb exp
156
- args = exp.args
157
- first_arg = args.first
156
+ first_arg = exp.first_arg
157
+ second_arg = exp.second_arg
158
158
 
159
- if symbol? first_arg and not hash? args.second
159
+ if symbol? first_arg and not hash? second_arg
160
160
  add_route first_arg
161
- elsif hash? args.second
162
- hash_iterate args.second do |k, v|
161
+ elsif hash? second_arg
162
+ hash_iterate second_arg do |k, v|
163
163
  if symbol? k and k.value == :to
164
164
  if string? v
165
165
  add_route_from_string v
@@ -194,12 +194,15 @@ class Brakeman::Rails3RoutesProcessor < Brakeman::BaseProcessor
194
194
  end
195
195
 
196
196
  def process_resources exp
197
- if exp.args and exp.args.second and exp.args.second.node_type == :hash
198
- self.current_controller = exp.first_arg.value
197
+ first_arg = exp.first_arg
198
+ second_arg = exp.second_arg
199
+
200
+ if second_arg and second_arg.node_type == :hash
201
+ self.current_controller = first_arg.value
199
202
  #handle hash
200
203
  add_resources_routes
201
204
  elsif exp.args.all? { |s| symbol? s }
202
- exp.args.each do |s|
205
+ exp.each_arg do |s|
203
206
  self.current_controller = s.value
204
207
  add_resources_routes
205
208
  end
@@ -211,7 +214,7 @@ class Brakeman::Rails3RoutesProcessor < Brakeman::BaseProcessor
211
214
 
212
215
  def process_resource exp
213
216
  #Does resource even take more than one controller name?
214
- exp.args.each do |s|
217
+ exp.each_arg do |s|
215
218
  if symbol? s
216
219
  self.current_controller = pluralize(s.value.to_s)
217
220
  add_resource_routes
@@ -252,8 +255,7 @@ class Brakeman::Rails3RoutesProcessor < Brakeman::BaseProcessor
252
255
  end
253
256
 
254
257
  def process_controller_block exp
255
- args = exp[1][3]
256
- self.current_controller = args[1][1]
258
+ self.current_controller = exp.block_call.first_arg.value
257
259
 
258
260
  in_controller_block do
259
261
  process exp[-1] if exp[-1]