brakeman 1.7.1 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/bin/brakeman +3 -0
  2. data/lib/brakeman.rb +2 -0
  3. data/lib/brakeman/brakeman.rake +4 -3
  4. data/lib/brakeman/checks/base_check.rb +40 -37
  5. data/lib/brakeman/checks/check_basic_auth.rb +3 -3
  6. data/lib/brakeman/checks/check_content_tag.rb +179 -0
  7. data/lib/brakeman/checks/check_cross_site_scripting.rb +41 -17
  8. data/lib/brakeman/checks/check_execute.rb +1 -1
  9. data/lib/brakeman/checks/check_file_access.rb +2 -2
  10. data/lib/brakeman/checks/check_link_to.rb +9 -7
  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 +6 -5
  14. data/lib/brakeman/checks/check_redirect.rb +18 -17
  15. data/lib/brakeman/checks/check_render.rb +3 -1
  16. data/lib/brakeman/checks/check_select_tag.rb +2 -2
  17. data/lib/brakeman/checks/check_select_vulnerability.rb +3 -3
  18. data/lib/brakeman/checks/check_send.rb +3 -3
  19. data/lib/brakeman/checks/check_session_settings.rb +5 -5
  20. data/lib/brakeman/checks/check_single_quotes.rb +8 -8
  21. data/lib/brakeman/checks/check_skip_before_filter.rb +2 -2
  22. data/lib/brakeman/checks/check_sql.rb +36 -39
  23. data/lib/brakeman/checks/check_validation_regex.rb +3 -3
  24. data/lib/brakeman/checks/check_without_protection.rb +2 -2
  25. data/lib/brakeman/format/style.css +15 -0
  26. data/lib/brakeman/options.rb +4 -0
  27. data/lib/brakeman/processor.rb +1 -1
  28. data/lib/brakeman/processors/alias_processor.rb +63 -61
  29. data/lib/brakeman/processors/base_processor.rb +31 -45
  30. data/lib/brakeman/processors/controller_alias_processor.rb +11 -9
  31. data/lib/brakeman/processors/controller_processor.rb +26 -25
  32. data/lib/brakeman/processors/erb_template_processor.rb +12 -12
  33. data/lib/brakeman/processors/erubis_template_processor.rb +19 -17
  34. data/lib/brakeman/processors/gem_processor.rb +5 -5
  35. data/lib/brakeman/processors/haml_template_processor.rb +16 -12
  36. data/lib/brakeman/processors/lib/find_all_calls.rb +11 -17
  37. data/lib/brakeman/processors/lib/find_call.rb +16 -23
  38. data/lib/brakeman/processors/lib/processor_helper.rb +11 -5
  39. data/lib/brakeman/processors/lib/rails2_config_processor.rb +21 -20
  40. data/lib/brakeman/processors/lib/rails2_route_processor.rb +38 -34
  41. data/lib/brakeman/processors/lib/rails3_config_processor.rb +17 -17
  42. data/lib/brakeman/processors/lib/rails3_route_processor.rb +42 -40
  43. data/lib/brakeman/processors/lib/render_helper.rb +6 -6
  44. data/lib/brakeman/processors/lib/route_helper.rb +1 -1
  45. data/lib/brakeman/processors/library_processor.rb +11 -11
  46. data/lib/brakeman/processors/model_processor.rb +18 -16
  47. data/lib/brakeman/processors/template_alias_processor.rb +36 -29
  48. data/lib/brakeman/processors/template_processor.rb +4 -4
  49. data/lib/brakeman/report.rb +23 -4
  50. data/lib/brakeman/templates/error_overview.html.erb +9 -1
  51. data/lib/brakeman/templates/view_warnings.html.erb +16 -3
  52. data/lib/brakeman/tracker.rb +3 -0
  53. data/lib/brakeman/util.rb +5 -1
  54. data/lib/brakeman/version.rb +1 -1
  55. data/lib/brakeman/warning.rb +1 -1
  56. data/lib/ruby_parser/bm_sexp.rb +302 -2
  57. metadata +6 -5
@@ -66,7 +66,7 @@ class Brakeman::ControllerAliasProcessor < Brakeman::AliasProcessor
66
66
  #(This method should be retired - only classes should ever be processed
67
67
  # and @current_module will never be set, leading to inaccurate class names)
68
68
  def process_class exp
69
- @current_class = class_name(exp[1])
69
+ @current_class = class_name(exp.class_name)
70
70
  if @current_module
71
71
  @current_class = ("#@current_module::#@current_class").to_sym
72
72
  end
@@ -77,13 +77,15 @@ class Brakeman::ControllerAliasProcessor < Brakeman::AliasProcessor
77
77
  #Processes a method definition, which may include
78
78
  #processing any rendered templates.
79
79
  def process_methdef exp
80
+ meth_name = exp.method_name
81
+
80
82
  #Skip if instructed to only process a specific method
81
83
  #(but don't skip if this method was called from elsewhere)
82
- return exp if @current_method.nil? and @only_method and @only_method != exp[1]
84
+ return exp if @current_method.nil? and @only_method and @only_method != meth_name
83
85
 
84
- is_route = route? exp[1]
86
+ is_route = route? meth_name
85
87
  other_method = @current_method
86
- @current_method = exp[1]
88
+ @current_method = meth_name
87
89
  @rendered = false if is_route
88
90
 
89
91
  env.scope do
@@ -95,7 +97,7 @@ class Brakeman::ControllerAliasProcessor < Brakeman::AliasProcessor
95
97
  end
96
98
  end
97
99
 
98
- process exp[3]
100
+ process exp.body
99
101
 
100
102
  if is_route and not @rendered
101
103
  process_default_render exp
@@ -110,7 +112,7 @@ class Brakeman::ControllerAliasProcessor < Brakeman::AliasProcessor
110
112
  def process_call exp
111
113
  exp = super
112
114
 
113
- if exp[2] == :head
115
+ if call? exp and exp.method == :head
114
116
  @rendered = true
115
117
  end
116
118
  exp
@@ -120,7 +122,7 @@ class Brakeman::ControllerAliasProcessor < Brakeman::AliasProcessor
120
122
  def process_call_with_block exp
121
123
  process_default exp
122
124
 
123
- if exp[1][2] == :respond_to
125
+ if call? exp.block_call and exp.block_call.method == :respond_to
124
126
  @rendered = true
125
127
  end
126
128
 
@@ -146,7 +148,7 @@ class Brakeman::ControllerAliasProcessor < Brakeman::AliasProcessor
146
148
  end
147
149
  else
148
150
  processor = Brakeman::AliasProcessor.new @tracker
149
- processor.process_safely(method[3])
151
+ processor.process_safely(method.body)
150
152
 
151
153
  ivars = processor.only_ivars(:include_request_vars).all
152
154
 
@@ -166,7 +168,7 @@ class Brakeman::ControllerAliasProcessor < Brakeman::AliasProcessor
166
168
 
167
169
  #Process template and add the current class and method name as called_from info
168
170
  def process_template name, args
169
- super name, args, "#@current_class##@current_method"
171
+ super name, args, ["#@current_class##@current_method"]
170
172
  end
171
173
 
172
174
  #Turns a method name into a template name
@@ -21,18 +21,19 @@ class Brakeman::ControllerProcessor < Brakeman::BaseProcessor
21
21
 
22
22
  #s(:class, NAME, PARENT, s(:scope ...))
23
23
  def process_class exp
24
+ name = class_name(exp.class_name)
25
+
24
26
  if @controller
25
- Brakeman.debug "[Notice] Skipping inner class: #{class_name exp[1]}"
27
+ Brakeman.debug "[Notice] Skipping inner class: #{name}"
26
28
  return ignore
27
29
  end
28
30
 
29
- name = class_name(exp[1])
30
31
  if @current_module
31
32
  name = (@current_module.to_s + "::" + name.to_s).to_sym
32
33
  end
33
34
 
34
35
  begin
35
- parent = class_name exp[2]
36
+ parent = class_name exp.parent_name
36
37
  rescue StandardError => e
37
38
  Brakeman.debug e
38
39
  parent = nil
@@ -48,7 +49,7 @@ class Brakeman::ControllerProcessor < Brakeman::BaseProcessor
48
49
  :src => exp,
49
50
  :file => @file_name }
50
51
  @tracker.controllers[@controller[:name]] = @controller
51
- exp[3] = process exp[3]
52
+ exp.body = process exp.body
52
53
  set_layout_name
53
54
  @controller = nil
54
55
  exp
@@ -56,18 +57,18 @@ class Brakeman::ControllerProcessor < Brakeman::BaseProcessor
56
57
 
57
58
  #Look for specific calls inside the controller
58
59
  def process_call exp
59
- target = exp[1]
60
+ target = exp.target
60
61
  if sexp? target
61
62
  target = process target
62
63
  end
63
64
 
64
- method = exp[2]
65
- args = exp[3]
65
+ method = exp.method
66
+ args = exp.args
66
67
 
67
68
  #Methods called inside class definition
68
69
  #like attr_* and other settings
69
70
  if @current_method.nil? and target.nil? and @controller
70
- if args.length == 1 #actually, empty
71
+ if args.empty?
71
72
  case method
72
73
  when :private, :protected, :public
73
74
  @visibility = method
@@ -79,21 +80,21 @@ class Brakeman::ControllerProcessor < Brakeman::BaseProcessor
79
80
  else
80
81
  case method
81
82
  when :include
82
- @controller[:includes] << class_name(args[1]) if @controller
83
+ @controller[:includes] << class_name(args.first) if @controller
83
84
  when :before_filter
84
85
  @controller[:options][:before_filters] ||= []
85
- @controller[:options][:before_filters] << args[1..-1]
86
+ @controller[:options][:before_filters] << args
86
87
  when :layout
87
- if string? args[-1]
88
+ if string? args.last
88
89
  #layout "some_layout"
89
90
 
90
- name = args[-1][1].to_s
91
+ name = args.last.value.to_s
91
92
  unless Dir.glob("#{@tracker.options[:app_path]}/app/views/layouts/#{name}.html.{erb,haml}").empty?
92
93
  @controller[:layout] = "layouts/#{name}"
93
94
  else
94
95
  Brakeman.debug "[Notice] Layout not found: #{name}"
95
96
  end
96
- elsif node_type? args[-1], :nil, :false
97
+ elsif node_type? args.last, :nil, :false
97
98
  #layout :false or layout nil
98
99
  @controller[:layout] = false
99
100
  end
@@ -115,7 +116,7 @@ class Brakeman::ControllerProcessor < Brakeman::BaseProcessor
115
116
  call.line(exp.line)
116
117
  call
117
118
  else
118
- call = Sexp.new :call, target, method, process(args)
119
+ call = Sexp.new :call, target, method, process(exp.arglist) #RP 3 TODO
119
120
  call.line(exp.line)
120
121
  call
121
122
  end
@@ -123,9 +124,9 @@ class Brakeman::ControllerProcessor < Brakeman::BaseProcessor
123
124
 
124
125
  #Process method definition and store in Tracker
125
126
  def process_defn exp
126
- name = exp[1]
127
+ name = exp.method_name
127
128
  @current_method = name
128
- res = Sexp.new :methdef, name, process(exp[2]), process(exp[3][1])
129
+ res = Sexp.new :methdef, name, process(exp[2]), process(exp.body.block)
129
130
  res.line(exp.line)
130
131
  @current_method = nil
131
132
  @controller[@visibility][name] = res unless @controller.nil?
@@ -135,7 +136,7 @@ class Brakeman::ControllerProcessor < Brakeman::BaseProcessor
135
136
 
136
137
  #Process self.method definition and store in Tracker
137
138
  def process_defs exp
138
- name = exp[2]
139
+ name = exp.method_name
139
140
 
140
141
  if exp[1].node_type == :self
141
142
  if @controller
@@ -150,7 +151,7 @@ class Brakeman::ControllerProcessor < Brakeman::BaseProcessor
150
151
  end
151
152
 
152
153
  @current_method = name
153
- res = Sexp.new :selfdef, target, name, process(exp[3]), process(exp[4][1])
154
+ res = Sexp.new :selfdef, target, name, process(exp[3]), process(exp.body.block)
154
155
  res.line(exp.line)
155
156
  @current_method = nil
156
157
  @controller[@visibility][name] = res unless @controller.nil?
@@ -160,7 +161,7 @@ class Brakeman::ControllerProcessor < Brakeman::BaseProcessor
160
161
 
161
162
  #Look for before_filters and add fake ones if necessary
162
163
  def process_iter exp
163
- if exp[1][2] == :before_filter
164
+ if exp.block_call.method == :before_filter
164
165
  add_fake_filter exp
165
166
  else
166
167
  super
@@ -185,20 +186,20 @@ class Brakeman::ControllerProcessor < Brakeman::BaseProcessor
185
186
  #methods and filters.
186
187
  def add_fake_filter exp
187
188
  filter_name = ("fake_filter" + rand.to_s[/\d+$/]).to_sym
188
- args = exp[1][3]
189
+ args = exp.block_call.arglist
189
190
  args.insert(1, Sexp.new(:lit, filter_name))
190
191
  before_filter_call = Sexp.new(:call, nil, :before_filter, args)
191
192
 
192
- if exp[2]
193
- block_variable = exp[2][1]
193
+ if exp.block_args
194
+ block_variable = exp.block_args[1]
194
195
  else
195
196
  block_variable = :temp
196
197
  end
197
198
 
198
- if node_type? exp[3], :block
199
- block_inner = exp[3][1..-1]
199
+ if node_type? exp.block, :block
200
+ block_inner = exp.block[1..-1]
200
201
  else
201
- block_inner = [exp[3]]
202
+ block_inner = [exp.block]
202
203
  end
203
204
 
204
205
  #Build Sexp for filter method
@@ -6,33 +6,33 @@ class Brakeman::ErbTemplateProcessor < Brakeman::TemplateProcessor
6
6
 
7
7
  #s(:call, TARGET, :method, s(:arglist))
8
8
  def process_call exp
9
- target = exp[1]
9
+ target = exp.target
10
10
  if sexp? target
11
11
  target = process target
12
12
  end
13
- method = exp[2]
13
+ method = exp.method
14
14
 
15
15
  #_erbout is the default output variable for erb
16
- if target and target[1] == :_erbout
16
+ if node_type? target, :lvar and target.value == :_erbout
17
17
  if method == :concat
18
18
  @inside_concat = true
19
- args = exp[3] = process(exp[3])
19
+ args = exp.arglist = process(exp.arglist)
20
20
  @inside_concat = false
21
21
 
22
22
  if args.length > 2
23
23
  raise Exception.new("Did not expect more than a single argument to _erbout.concat")
24
24
  end
25
25
 
26
- args = args[1]
26
+ arg = args[1]
27
27
 
28
- if args.node_type == :call and args[2] == :to_s #erb always calls to_s on output
29
- args = args[1]
28
+ if arg.node_type == :call and arg.method == :to_s #erb always calls to_s on output
29
+ arg = arg.target
30
30
  end
31
31
 
32
- if args.node_type == :str #ignore plain strings
32
+ if arg.node_type == :str #ignore plain strings
33
33
  ignore
34
34
  else
35
- s = Sexp.new :output, args
35
+ s = Sexp.new :output, arg
36
36
  s.line(exp.line)
37
37
  @current_template[:outputs] << s
38
38
  s
@@ -43,11 +43,11 @@ class Brakeman::ErbTemplateProcessor < Brakeman::TemplateProcessor
43
43
  abort "Unrecognized action on _erbout: #{method}"
44
44
  end
45
45
  elsif target == nil and method == :render
46
- exp[3] = process(exp[3])
46
+ exp.arglist = process(exp.arglist)
47
47
  make_render_in_view exp
48
48
  else
49
49
  #TODO: Is it really necessary to create a new Sexp here?
50
- args = exp[3] = process(exp[3])
50
+ args = exp.arglist = process(exp.arglist)
51
51
  call = Sexp.new :call, target, method, args
52
52
  call.original_line(exp.original_line)
53
53
  call.line(exp.line)
@@ -70,7 +70,7 @@ class Brakeman::ErbTemplateProcessor < Brakeman::TemplateProcessor
70
70
  res = process e
71
71
  if res.empty? or res == ignore
72
72
  nil
73
- elsif node_type?(res, :lvar) and res[1] == :_erbout
73
+ elsif node_type?(res, :lvar) and res.value == :_erbout
74
74
  nil
75
75
 
76
76
  else
@@ -5,31 +5,33 @@ class Brakeman::ErubisTemplateProcessor < Brakeman::TemplateProcessor
5
5
 
6
6
  #s(:call, TARGET, :method, s(:arglist))
7
7
  def process_call exp
8
- target = exp[1]
8
+ target = exp.target
9
9
  if sexp? target
10
10
  target = process target
11
11
  end
12
- method = exp[2]
12
+ method = exp.method
13
13
 
14
14
  #_buf is the default output variable for Erubis
15
- if target and (target[1] == :_buf or target[1] == :@output_buffer)
15
+ if node_type?(target, :lvar, :ivar) and (target.value == :_buf or target.value == :@output_buffer)
16
16
  if method == :<< or method == :safe_concat
17
- args = exp[3][1] = process(exp[3][1])
17
+ exp.arglist = process exp.arglist
18
+
19
+ arg = exp.first_arg
18
20
 
19
21
  #We want the actual content
20
- if args.node_type == :call and (args[2] == :to_s or args[2] == :html_safe!)
21
- args = args[1]
22
+ if arg.node_type == :call and (arg.method == :to_s or arg.method == :html_safe!)
23
+ arg = arg.target
22
24
  end
23
25
 
24
- if args.node_type == :str #ignore plain strings
26
+ if arg.node_type == :str #ignore plain strings
25
27
  ignore
26
- elsif target[1] == :@output_buffer
27
- s = Sexp.new :escaped_output, args
28
+ elsif node_type? target, :ivar and target.value == :@output_buffer
29
+ s = Sexp.new :escaped_output, arg
28
30
  s.line(exp.line)
29
31
  @current_template[:outputs] << s
30
32
  s
31
33
  else
32
- s = Sexp.new :output, args
34
+ s = Sexp.new :output, arg
33
35
  s.line(exp.line)
34
36
  @current_template[:outputs] << s
35
37
  s
@@ -40,11 +42,11 @@ class Brakeman::ErubisTemplateProcessor < Brakeman::TemplateProcessor
40
42
  abort "Unrecognized action on buffer: #{method}"
41
43
  end
42
44
  elsif target == nil and method == :render
43
- exp[3] = process exp[3]
45
+ exp.arglist = process exp.arglist
44
46
  make_render_in_view exp
45
47
  else
46
48
  #TODO: Is it really necessary to create a new Sexp here?
47
- args = exp[3] = process(exp[3])
49
+ args = exp.arglist = process(exp.arglist)
48
50
  call = Sexp.new :call, target, method, args
49
51
  call.original_line(exp.original_line)
50
52
  call.line(exp.line)
@@ -72,14 +74,14 @@ class Brakeman::ErubisTemplateProcessor < Brakeman::TemplateProcessor
72
74
  # @output_buffer.append = some_output
73
75
  # @output_buffer.safe_append = some_output
74
76
  def process_attrasgn exp
75
- if exp[1].node_type == :ivar and exp[1][1] == :@output_buffer
76
- if exp[2] == :append= or exp[2] == :safe_append=
77
- args = exp[3][1] = process(exp[3][1])
77
+ if exp.target.node_type == :ivar and exp.target.value == :@output_buffer
78
+ if exp.method == :append= or exp.method == :safe_append=
79
+ arg = exp.first_arg = process(exp.first_arg)
78
80
 
79
- if args.node_type == :str
81
+ if arg.node_type == :str
80
82
  ignore
81
83
  else
82
- s = Sexp.new :escaped_output, args
84
+ s = Sexp.new :escaped_output, arg
83
85
  s.line(exp.line)
84
86
  @current_template[:outputs] << s
85
87
  s
@@ -26,13 +26,13 @@ class Brakeman::GemProcessor < Brakeman::BaseProcessor
26
26
  end
27
27
 
28
28
  def process_call exp
29
- if exp[1] == nil and exp[2] == :gem
30
- args = exp[3][1..-1]
29
+ if exp.target == nil and exp.method == :gem
30
+ args = exp.args
31
31
 
32
- if sexp? args[1]
33
- @tracker.config[:gems][args[0][1].to_sym] = args[1][1]
32
+ if string? args.second
33
+ @tracker.config[:gems][args.first.value.to_sym] = args.second.value
34
34
  else
35
- @tracker.config[:gems][args[0][1].to_sym] = ">=0.0.0"
35
+ @tracker.config[:gems][args.first.value.to_sym] = ">=0.0.0"
36
36
  end
37
37
  end
38
38
 
@@ -22,29 +22,29 @@ class Brakeman::HamlTemplateProcessor < Brakeman::TemplateProcessor
22
22
 
23
23
  #Processes call, looking for template output
24
24
  def process_call exp
25
- target = exp[1]
25
+ target = exp.target
26
26
  if sexp? target
27
27
  target = process target
28
28
  end
29
29
 
30
- method = exp[2]
30
+ method = exp.method
31
31
 
32
- if (sexp? target and target[2] == :_hamlout) or target == :_hamlout
32
+ if (call? target and target.method == :_hamlout) or target == :_hamlout
33
33
  res = case method
34
34
  when :adjust_tabs, :rstrip!, :attributes #Check attributes, maybe?
35
35
  ignore
36
36
  when :options
37
- Sexp.new :call, :_hamlout, :options, exp[3]
37
+ Sexp.new :call, :_hamlout, :options, exp.arglist
38
38
  when :buffer
39
- Sexp.new :call, :_hamlout, :buffer, exp[3]
39
+ Sexp.new :call, :_hamlout, :buffer, exp.arglist
40
40
  when :open_tag
41
- Sexp.new(:tag, process(exp[3]))
41
+ Sexp.new(:tag, process(exp.arglist))
42
42
  else
43
- arg = exp[3][1]
43
+ arg = exp.first_arg
44
44
 
45
45
  if arg
46
46
  @inside_concat = true
47
- out = exp[3][1] = process(arg)
47
+ out = exp.arglist[1] = process(arg)
48
48
  @inside_concat = false
49
49
  else
50
50
  raise Exception.new("Empty _hamlout.#{method}()?")
@@ -78,7 +78,7 @@ class Brakeman::HamlTemplateProcessor < Brakeman::TemplateProcessor
78
78
  #This seems to be used rarely, but directly appends args to output buffer
79
79
  elsif sexp? target and method == :<< and is_buffer_target? target
80
80
  @inside_concat = true
81
- out = exp[3][1] = process(exp[3][1])
81
+ out = exp.arglist[1] = process(exp.arglist[1])
82
82
  @inside_concat = false
83
83
 
84
84
  if out.node_type == :str #ignore plain strings
@@ -91,11 +91,11 @@ class Brakeman::HamlTemplateProcessor < Brakeman::TemplateProcessor
91
91
  end
92
92
  elsif target == nil and method == :render
93
93
  #Process call to render()
94
- exp[3] = process exp[3]
94
+ exp.arglist = process exp.arglist
95
95
  make_render_in_view exp
96
96
  else
97
97
  #TODO: Do we really need a new Sexp here?
98
- args = process exp[3]
98
+ args = process exp.arglist
99
99
  call = Sexp.new :call, target, method, args
100
100
  call.original_line(exp.original_line)
101
101
  call.line(exp.line)
@@ -127,7 +127,11 @@ class Brakeman::HamlTemplateProcessor < Brakeman::TemplateProcessor
127
127
  end
128
128
 
129
129
  #Checks if the buffer is the target in a method call Sexp.
130
+ #TODO: Test this
130
131
  def is_buffer_target? exp
131
- exp.node_type == :call and exp[1] == :_hamlout and exp[2] == :buffer
132
+ exp.node_type == :call and
133
+ node_type? exp.target, :lvar and
134
+ exp.target.value == :_hamlout and
135
+ exp.method == :buffer
132
136
  end
133
137
  end