brakeman 1.7.1 → 1.8.0

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 (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