brakeman 0.3.2 → 0.4.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.
@@ -38,6 +38,10 @@ OptionParser.new do |opts|
38
38
  options[:ignore_model_output] = true
39
39
  end
40
40
 
41
+ opts.on "-e", "--escape-html", "Escape HTML by default" do
42
+ options[:escape_html] = true
43
+ end
44
+
41
45
  opts.on "-r", "--report-direct", "Only report direct use of untrusted data" do |option|
42
46
  options[:check_arguments] = !option
43
47
  end
@@ -30,6 +30,8 @@ class CheckCrossSiteScripting < BaseCheck
30
30
 
31
31
  HAML_HELPERS = Sexp.new(:colon2, Sexp.new(:const, :Haml), :Helpers)
32
32
 
33
+ XML_HELPER = Sexp.new(:colon2, Sexp.new(:const, :Erubis), :XmlHelper)
34
+
33
35
  URI = Sexp.new(:const, :URI)
34
36
 
35
37
  CGI = Sexp.new(:const, :CGI)
@@ -48,7 +50,7 @@ class CheckCrossSiteScripting < BaseCheck
48
50
  @current_template = template
49
51
 
50
52
  template[:outputs].each do |out|
51
- type, match = has_immediate_user_input?(out[1])
53
+ type, match = (out[0] == :output and has_immediate_user_input?(out[1]))
52
54
  if type and not duplicate? out
53
55
  add_result out
54
56
  case type
@@ -102,6 +104,16 @@ class CheckCrossSiteScripting < BaseCheck
102
104
  process exp[1].dup
103
105
  end
104
106
 
107
+ #Look for calls to raw()
108
+ #Otherwise, ignore
109
+ def process_escaped_output exp
110
+ if exp[1].node_type == :call and exp[1][2] == :raw
111
+ process_output exp
112
+ else
113
+ exp
114
+ end
115
+ end
116
+
105
117
  #Check a call for user input
106
118
  #
107
119
  #
@@ -154,6 +166,7 @@ class CheckCrossSiteScripting < BaseCheck
154
166
  (@matched == :model and IGNORE_MODEL_METHODS.include? method) or
155
167
  (target == HAML_HELPERS and method == :html_escape) or
156
168
  ((target == URI or target == CGI) and method == :escape) or
169
+ (target == XML_HELPER and method == :escape_xml) or
157
170
  (target == FORM_BUILDER and IGNORE_METHODS.include? method) or
158
171
  (method.to_s[-1,1] == "?")
159
172
 
@@ -163,7 +176,6 @@ class CheckCrossSiteScripting < BaseCheck
163
176
 
164
177
  @matched = :model
165
178
  elsif @inspect_arguments and (ALL_PARAMETERS.include?(exp) or params? exp)
166
-
167
179
  @matched = :params
168
180
  elsif @inspect_arguments
169
181
  process args
@@ -50,6 +50,8 @@ class Processor
50
50
  result = ErbTemplateProcessor.new(@tracker, name, called_from, file_name).process src
51
51
  when :haml
52
52
  result = HamlTemplateProcessor.new(@tracker, name, called_from, file_name).process src
53
+ when :erubis
54
+ result = ErubisTemplateProcessor.new(@tracker, name, called_from, file_name).process src
53
55
  else
54
56
  abort "Unknown template type: #{type} (#{name})"
55
57
  end
@@ -2,6 +2,7 @@ require 'processors/template_processor'
2
2
 
3
3
  #Processes ERB templates using Erubis instead of erb.
4
4
  class ErubisTemplateProcessor < TemplateProcessor
5
+
5
6
 
6
7
  #s(:call, TARGET, :method, s(:arglist))
7
8
  def process_call exp
@@ -10,10 +11,10 @@ class ErubisTemplateProcessor < TemplateProcessor
10
11
  target = process target
11
12
  end
12
13
  method = exp[2]
13
-
14
+
14
15
  #_buf is the default output variable for Erubis
15
- if target and target[1] == :_buf
16
- if method == :<<
16
+ if target and (target[1] == :_buf or target[1] == :output_buffer)
17
+ if method == :<< or method == :safe_concat
17
18
  args = exp[3][1] = process(exp[3][1])
18
19
 
19
20
  if args.node_type == :call and args[2] == :to_s #just calling to_s on inner code
@@ -59,4 +60,26 @@ class ErubisTemplateProcessor < TemplateProcessor
59
60
  block.line(exp.line)
60
61
  block
61
62
  end
63
+
64
+ #Look for assignments to output buffer
65
+ def process_attrasgn exp
66
+ if exp[1].node_type == :ivar and exp[1][1] == :@output_buffer
67
+ if exp[2] == :append= or exp[2] == :safe_append=
68
+ args = exp[3][1] = process(exp[3][1])
69
+
70
+ if args.node_type == :str
71
+ ignore
72
+ else
73
+ s = Sexp.new :escaped_output, args
74
+ s.line(exp.line)
75
+ @current_template[:outputs] << s
76
+ s
77
+ end
78
+ else
79
+ ignore
80
+ end
81
+ else
82
+ super
83
+ end
84
+ end
62
85
  end
@@ -153,6 +153,23 @@ class OutputProcessor < Ruby2Ruby
153
153
  out
154
154
  end
155
155
 
156
+ def process_escaped_output exp
157
+ out = if exp[0].node_type == :str
158
+ ""
159
+ else
160
+ res = process exp[0]
161
+
162
+ if res == ""
163
+ ""
164
+ else
165
+ "[Escaped Output] #{res}"
166
+ end
167
+ end
168
+ exp.clear
169
+ out
170
+ end
171
+
172
+
156
173
  def process_format exp
157
174
  out = if exp[0].node_type == :str or exp[0].node_type == :ignore
158
175
  ""
@@ -17,6 +17,10 @@ class ScannerErubis < Erubis::Eruby
17
17
  include Erubis::NoTextEnhancer
18
18
  end
19
19
 
20
+ class ErubisEscape < ScannerErubis
21
+ include Erubis::EscapeEnhancer
22
+ end
23
+
20
24
  #Scans the Rails application.
21
25
  class Scanner
22
26
 
@@ -61,7 +65,9 @@ class Scanner
61
65
  @processor.process_config(RubyParser.new.parse(File.read("#@path/config/gems.rb")))
62
66
  end
63
67
 
64
- if File.exists? "#@path/vendor/plugins/rails_xss" or OPTIONS[:rails3]
68
+ if File.exists? "#@path/vendor/plugins/rails_xss" or
69
+ OPTIONS[:rails3] or OPTIONS[:escape_html] or
70
+ (File.exists? "#@path/Gemfile" and File.read("#@path/Gemfile").include? "rails_xss")
65
71
  tracker.config[:escape_html] = true
66
72
  warn "[Notice] Escaping HTML by default"
67
73
  end
@@ -143,8 +149,14 @@ class Scanner
143
149
  begin
144
150
  if type == :erb
145
151
  if tracker.config[:escape_html]
146
- src = RailsXSSErubis.new(File.read(f)).src
152
+ type = :erubis
153
+ if OPTIONS[:rails3]
154
+ src = RailsXSSErubis.new(File.read(f)).src
155
+ else
156
+ src = ErubisEscape.new(File.read(f)).src
157
+ end
147
158
  elsif tracker.config[:erubis]
159
+ type = :erubis
148
160
  src = ScannerErubis.new(File.read(f)).src
149
161
  else
150
162
  src = ERB.new(File.read(f), nil, "-").src
@@ -200,34 +212,49 @@ class Scanner
200
212
  end
201
213
  end
202
214
 
203
- #This is from the rails_xss plugin,
204
- #except we don't care about plain text.
215
+ #This is from Rails 3 version of the Erubis handler
205
216
  class RailsXSSErubis < ::Erubis::Eruby
206
217
  include Erubis::NoTextEnhancer
207
218
 
208
219
  #Initializes output buffer.
209
220
  def add_preamble(src)
210
- src << "@output_buffer = ActionView::SafeBuffer.new;\n"
221
+ # src << "_buf = ActionView::SafeBuffer.new;\n"
211
222
  end
212
223
 
213
224
  #This does nothing.
214
225
  def add_text(src, text)
215
- # src << "@output_buffer << ('" << escape_text(text) << "'.html_safe!);"
226
+ # src << "@output_buffer << ('" << escape_text(text) << "'.html_safe!);"
216
227
  end
217
228
 
218
- #Add an expression to the output buffer _without_ escaping.
229
+ BLOCK_EXPR = /\s+(do|\{)(\s*\|[^|]*\|)?\s*\Z/
230
+
219
231
  def add_expr_literal(src, code)
220
- src << '@output_buffer << ((' << code << ').to_s);'
232
+ if code =~ BLOCK_EXPR
233
+ src << '@output_buffer.append= ' << code
234
+ else
235
+ src << '@output_buffer.append= (' << code << ');'
236
+ end
237
+ end
238
+
239
+ def add_stmt(src, code)
240
+ if code =~ BLOCK_EXPR
241
+ src << '@output_buffer.append_if_string= ' << code
242
+ else
243
+ super
244
+ end
221
245
  end
222
246
 
223
- #Add an expression to the output buffer after escaping it.
224
247
  def add_expr_escaped(src, code)
225
- src << '@output_buffer << ' << escaped_expr(code) << ';'
248
+ if code =~ BLOCK_EXPR
249
+ src << "@output_buffer.safe_append= " << code
250
+ else
251
+ src << "@output_buffer.safe_concat(" << code << ");"
252
+ end
226
253
  end
227
254
 
228
255
  #Add code to output buffer.
229
256
  def add_postamble(src)
230
- src << '@output_buffer.to_s'
257
+ # src << '_buf.to_s'
231
258
  end
232
259
  end
233
260
 
@@ -1 +1 @@
1
- Version = "0.3.2"
1
+ Version = "0.4.0"
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 3
8
- - 2
9
- version: 0.3.2
7
+ - 4
8
+ - 0
9
+ version: 0.4.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Justin Collins
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-05-12 00:00:00 -07:00
17
+ date: 2011-05-18 00:00:00 -07:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency