brakeman 1.8.3 → 1.9.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
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]