brakeman 1.5.2 → 1.5.3

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.
data/README.md CHANGED
@@ -41,6 +41,10 @@ To specify an output file for the results:
41
41
 
42
42
  The output format is determined by the file extension or by using the `-f` option. Current options are: `text`, `html`, `tabs`, `json` and `csv`.
43
43
 
44
+ Multiple output files can be specified:
45
+
46
+ brakeman -o output.html -o output.json
47
+
44
48
  To suppress informational warnings and just output the report:
45
49
 
46
50
  brakeman -q
@@ -27,8 +27,8 @@ module Brakeman
27
27
  # * :ignore_model_output - consider models safe (default: false)
28
28
  # * :message_limit - limit length of messages
29
29
  # * :min_confidence - minimum confidence (0-2, 0 is highest)
30
- # * :output_file - file for output
31
- # * :output_format - format for output (:to_s, :to_tabs, :to_csv, :to_html)
30
+ # * :output_files - files for output
31
+ # * :output_formats - formats for output (:to_s, :to_tabs, :to_csv, :to_html)
32
32
  # * :parallel_checks - run checks in parallel (default: true)
33
33
  # * :print_report - if no output file specified, print to stdout (default: false)
34
34
  # * :quiet - suppress most messages (default: true)
@@ -65,7 +65,7 @@ module Brakeman
65
65
 
66
66
  options = load_options(options[:config_file]).merge! options
67
67
  options = get_defaults.merge! options
68
- options[:output_format] = get_output_format options
68
+ options[:output_formats] = get_output_formats options
69
69
 
70
70
  app_path = options[:app_path]
71
71
 
@@ -124,39 +124,47 @@ module Brakeman
124
124
  }
125
125
  end
126
126
 
127
- #Determine output format based on options[:output_format]
128
- #or options[:output_file]
129
- def self.get_output_format options
127
+ #Determine output formats based on options[:output_formats]
128
+ #or options[:output_files]
129
+ def self.get_output_formats options
130
130
  #Set output format
131
+ if options[:output_format] && options[:output_files] && options[:output_files].size > 1
132
+ raise ArgumentError, "Cannot specify output format if multiple output files specified"
133
+ end
131
134
  if options[:output_format]
132
- case options[:output_format]
133
- when :html, :to_html
134
- :to_html
135
- when :csv, :to_csv
136
- :to_csv
137
- when :pdf, :to_pdf
138
- :to_pdf
139
- when :tabs, :to_tabs
140
- :to_tabs
141
- when :json, :to_json
142
- :to_json
143
- else
144
- :to_s
145
- end
135
+ [
136
+ case options[:output_format]
137
+ when :html, :to_html
138
+ :to_html
139
+ when :csv, :to_csv
140
+ :to_csv
141
+ when :pdf, :to_pdf
142
+ :to_pdf
143
+ when :tabs, :to_tabs
144
+ :to_tabs
145
+ when :json, :to_json
146
+ :to_json
147
+ else
148
+ :to_s
149
+ end
150
+ ]
146
151
  else
147
- case options[:output_file]
148
- when /\.html$/i
149
- :to_html
150
- when /\.csv$/i
151
- :to_csv
152
- when /\.pdf$/i
153
- :to_pdf
154
- when /\.tabs$/i
155
- :to_tabs
156
- when /\.json$/i
157
- :to_json
158
- else
159
- :to_s
152
+ return [:to_s] unless options[:output_files]
153
+ options[:output_files].map do |output_file|
154
+ case output_file
155
+ when /\.html$/i
156
+ :to_html
157
+ when /\.csv$/i
158
+ :to_csv
159
+ when /\.pdf$/i
160
+ :to_pdf
161
+ when /\.tabs$/i
162
+ :to_tabs
163
+ when /\.json$/i
164
+ :to_json
165
+ else
166
+ :to_s
167
+ end
160
168
  end
161
169
  end
162
170
  end
@@ -253,17 +261,21 @@ module Brakeman
253
261
  end
254
262
  tracker.run_checks
255
263
 
256
- if options[:output_file]
264
+ if options[:output_files]
257
265
  notify "Generating report..."
258
266
 
259
- File.open options[:output_file], "w" do |f|
260
- f.puts tracker.report.send(options[:output_format])
267
+ options[:output_files].each_with_index do |output_file, idx|
268
+ File.open output_file, "w" do |f|
269
+ f.write tracker.report.send(options[:output_formats][idx])
270
+ end
271
+ notify "Report saved in '#{output_file}'"
261
272
  end
262
- notify "Report saved in '#{options[:output_file]}'"
263
273
  elsif options[:print_report]
264
274
  notify "Generating report..."
265
275
 
266
- puts tracker.report.send(options[:output_format])
276
+ options[:output_formats].each do |output_format|
277
+ puts tracker.report.send(output_format)
278
+ end
267
279
  end
268
280
 
269
281
  tracker
@@ -0,0 +1,9 @@
1
+ namespace :brakeman do
2
+
3
+ desc "Run Brakeman"
4
+ task :run, :output_file do |t, args|
5
+ require 'brakeman'
6
+
7
+ Brakeman.run :app_path => ".", :output_file => args[:output_file], :print_report => true
8
+ end
9
+ end
@@ -18,9 +18,9 @@ class Brakeman::CheckEvaluation < Brakeman::BaseCheck
18
18
  end
19
19
  end
20
20
 
21
- #Warns if result includes user input
21
+ #Warns if eval includes user input
22
22
  def process_result result
23
- if include_user_input? result[:call]
23
+ if include_user_input? result[:call][-1]
24
24
  warn :result => result,
25
25
  :warning_type => "Dangerous Eval",
26
26
  :message => "User input in eval",
@@ -0,0 +1,38 @@
1
+ require 'brakeman/checks/base_check'
2
+
3
+ #Checks if user supplied data is passed to send
4
+ class Brakeman::CheckSend < Brakeman::BaseCheck
5
+ Brakeman::Checks.add self
6
+
7
+ @description = "Check for unsafe use of Object#send"
8
+
9
+ def run_check
10
+ Brakeman.debug("Finding instances of #send")
11
+ calls = tracker.find_call :method => :send
12
+
13
+ calls.each do |call|
14
+ process_result call
15
+ end
16
+ end
17
+
18
+ def process_result result
19
+ args = process result[:call][3]
20
+ target = process result[:call][1]
21
+
22
+ if has_immediate_user_input? args[1]
23
+ warn :result => result,
24
+ :warning_type => "Dangerous Send",
25
+ :message => "User controlled method execution",
26
+ :code => result[:call],
27
+ :confidence => CONFIDENCE[:high]
28
+ end
29
+
30
+ if has_immediate_user_input?(target)
31
+ warn :result => result,
32
+ :warning_type => "Dangerous Send",
33
+ :message => "User defined target of method invocation",
34
+ :code => result[:call],
35
+ :confidence => CONFIDENCE[:med]
36
+ end
37
+ end
38
+ end
@@ -130,7 +130,7 @@ module Brakeman::Options
130
130
  opts.on "-f",
131
131
  "--format TYPE",
132
132
  [:pdf, :text, :html, :csv, :tabs, :json],
133
- "Specify output format. Default is text" do |type|
133
+ "Specify output formats. Default is text" do |type|
134
134
 
135
135
  type = "s" if type == :text
136
136
  options[:output_format] = ("to_" << type.to_s).to_sym
@@ -152,8 +152,9 @@ module Brakeman::Options
152
152
  options[:message_limit] = limit.to_i
153
153
  end
154
154
 
155
- opts.on "-o", "--output FILE", "Specify file for output. Defaults to stdout" do |file|
156
- options[:output_file] = file
155
+ opts.on "-o", "--output FILE", "Specify files for output. Defaults to stdout. Multiple '-o's allowed" do |file|
156
+ options[:output_files] ||= []
157
+ options[:output_files].push(file)
157
158
  end
158
159
 
159
160
  opts.on "--separate-models", "Warn on each model without attr_accessible" do
@@ -0,0 +1,4 @@
1
+ #Erubis processor which ignores any output which is plain text.
2
+ class Brakeman::ScannerErubis < Erubis::Eruby
3
+ include Erubis::NoTextEnhancer
4
+ end
@@ -0,0 +1,46 @@
1
+ #This is from the rails_xss plugin for Rails 2
2
+ class Brakeman::Rails2XSSPluginErubis < ::Erubis::Eruby
3
+ def add_preamble(src)
4
+ #src << "@output_buffer = ActiveSupport::SafeBuffer.new;"
5
+ end
6
+
7
+ #This is different from rails_xss - fixes some line number issues
8
+ def add_text(src, text)
9
+ if text == "\n"
10
+ src << "\n"
11
+ elsif text.include? "\n"
12
+ lines = text.split("\n")
13
+ if text.match(/\n\z/)
14
+ lines.each do |line|
15
+ src << "@output_buffer.safe_concat('" << escape_text(line) << "');\n"
16
+ end
17
+ else
18
+ lines[0..-2].each do |line|
19
+ src << "@output_buffer.safe_concat('" << escape_text(line) << "');\n"
20
+ end
21
+
22
+ src << "@output_buffer.safe_concat('" << escape_text(lines.last) << "');"
23
+ end
24
+ else
25
+ src << "@output_buffer.safe_concat('" << escape_text(text) << "');"
26
+ end
27
+ end
28
+
29
+ BLOCK_EXPR = /\s+(do|\{)(\s*\|[^|]*\|)?\s*\Z/
30
+
31
+ def add_expr_literal(src, code)
32
+ if code =~ BLOCK_EXPR
33
+ src << "@output_buffer.safe_concat((" << $1 << ").to_s);"
34
+ else
35
+ src << '@output_buffer << ((' << code << ').to_s);'
36
+ end
37
+ end
38
+
39
+ def add_expr_escaped(src, code)
40
+ src << '@output_buffer << ' << escaped_expr(code) << ';'
41
+ end
42
+
43
+ def add_postamble(src)
44
+ #src << '@output_buffer.to_s'
45
+ end
46
+ end
@@ -0,0 +1,60 @@
1
+ #This is from Rails 3 version of the Erubis handler
2
+ class Brakeman::Rails3Erubis < ::Erubis::Eruby
3
+
4
+ def add_preamble(src)
5
+ # src << "_buf = ActionView::SafeBuffer.new;\n"
6
+ end
7
+
8
+ #This is different from Rails 3 - fixes some line number issues
9
+ def add_text(src, text)
10
+ if text == "\n"
11
+ src << "\n"
12
+ elsif text.include? "\n"
13
+ lines = text.split("\n")
14
+ if text.match(/\n\z/)
15
+ lines.each do |line|
16
+ src << "@output_buffer << ('" << escape_text(line) << "'.html_safe!);\n"
17
+ end
18
+ else
19
+ lines[0..-2].each do |line|
20
+ src << "@output_buffer << ('" << escape_text(line) << "'.html_safe!);\n"
21
+ end
22
+
23
+ src << "@output_buffer << ('" << escape_text(lines.last) << "'.html_safe!);"
24
+ end
25
+ else
26
+ src << "@output_buffer << ('" << escape_text(text) << "'.html_safe!);"
27
+ end
28
+ end
29
+
30
+ BLOCK_EXPR = /\s+(do|\{)(\s*\|[^|]*\|)?\s*\Z/
31
+
32
+ def add_expr_literal(src, code)
33
+ if code =~ BLOCK_EXPR
34
+ src << '@output_buffer.append= ' << code
35
+ else
36
+ src << '@output_buffer.append= (' << code << ');'
37
+ end
38
+ end
39
+
40
+ def add_stmt(src, code)
41
+ if code =~ BLOCK_EXPR
42
+ src << '@output_buffer.append_if_string= ' << code
43
+ else
44
+ super
45
+ end
46
+ end
47
+
48
+ def add_expr_escaped(src, code)
49
+ if code =~ BLOCK_EXPR
50
+ src << "@output_buffer.safe_append= " << code
51
+ else
52
+ src << "@output_buffer.safe_concat(" << code << ");"
53
+ end
54
+ end
55
+
56
+ #Add code to output buffer.
57
+ def add_postamble(src)
58
+ # src << '_buf.to_s'
59
+ end
60
+ end
@@ -40,8 +40,8 @@ module Brakeman
40
40
 
41
41
  #Process variable aliasing in controller source and save it in the
42
42
  #tracker.
43
- def process_controller_alias src, only_method = nil
44
- ControllerAliasProcessor.new(@tracker, only_method).process src
43
+ def process_controller_alias name, src, only_method = nil
44
+ ControllerAliasProcessor.new(@tracker, only_method).process_controller name, src
45
45
  end
46
46
 
47
47
  #Process a model source
@@ -492,12 +492,25 @@ class Brakeman::AliasProcessor < SexpProcessor
492
492
 
493
493
  #Returns a new SexpProcessor::Environment containing only instance variables.
494
494
  #This is useful, for example, when processing views.
495
- def only_ivars
495
+ def only_ivars include_request_vars = false
496
496
  res = SexpProcessor::Environment.new
497
- env.all.each do |k, v|
498
- #TODO Why would this have nil values?
499
- res[k] = v.dup if k.node_type == :ivar and not v.nil?
497
+
498
+ if include_request_vars
499
+ env.all.each do |k, v|
500
+ #TODO Why would this have nil values?
501
+ if (k.node_type == :ivar or request_value? k) and not v.nil?
502
+ res[k] = v.dup
503
+ end
504
+ end
505
+ else
506
+ env.all.each do |k, v|
507
+ #TODO Why would this have nil values?
508
+ if k.node_type == :ivar and not v.nil?
509
+ res[k] = v.dup
510
+ end
511
+ end
500
512
  end
513
+
501
514
  res
502
515
  end
503
516
 
@@ -32,14 +32,6 @@ class Brakeman::BaseProcessor < SexpProcessor
32
32
  exp
33
33
  end
34
34
 
35
- def process_module exp
36
- current_module = @current_module
37
- @current_module = class_name exp[1]
38
- process exp[2]
39
- @current_module = current_module
40
- exp
41
- end
42
-
43
35
  #Process a new scope. Removes expressions that are set to nil.
44
36
  def process_scope exp
45
37
  exp = exp.dup
@@ -210,9 +202,14 @@ class Brakeman::BaseProcessor < SexpProcessor
210
202
  exp
211
203
  end
212
204
 
205
+ #Convenience method for `make_render exp, true`
206
+ def make_render_in_view exp
207
+ make_render exp, true
208
+ end
209
+
213
210
  #Generates :render node from call to render.
214
- def make_render exp
215
- render_type, value, rest = find_render_type exp[3]
211
+ def make_render exp, in_view = false
212
+ render_type, value, rest = find_render_type exp[3], in_view
216
213
  rest = process rest
217
214
  result = Sexp.new(:render, render_type, value, rest)
218
215
  result.line(exp.line)
@@ -222,9 +219,11 @@ class Brakeman::BaseProcessor < SexpProcessor
222
219
  #Determines the type of a call to render.
223
220
  #
224
221
  #Possible types are:
225
- #:action, :default :file, :inline, :js, :json, :nothing, :partial,
222
+ #:action, :default, :file, :inline, :js, :json, :nothing, :partial,
226
223
  #:template, :text, :update, :xml
227
- def find_render_type args
224
+ #
225
+ #And also :layout for inside templates
226
+ def find_render_type args, in_view = false
228
227
  rest = Sexp.new(:hash)
229
228
  type = nil
230
229
  value = nil
@@ -252,10 +251,18 @@ class Brakeman::BaseProcessor < SexpProcessor
252
251
  value = args[1]
253
252
  end
254
253
 
254
+ types_in_hash = Set[:action, :file, :inline, :js, :json, :nothing, :partial, :text, :update, :xml]
255
+
256
+ #render :layout => "blah" means something else when in a template
257
+ if in_view
258
+ types_in_hash << :layout
259
+ end
260
+
261
+ #Look for "type" of render in options hash
262
+ #For example, render :file => "blah"
255
263
  if hash? args[-1]
256
264
  hash_iterate(args[-1]) do |key, val|
257
- case key[1]
258
- when :action, :file, :inline, :js, :json, :nothing, :partial, :text, :update, :xml
265
+ if types_in_hash.include? key[1]
259
266
  type = key[1]
260
267
  value = val
261
268
  else
@@ -17,11 +17,23 @@ class Brakeman::ControllerAliasProcessor < Brakeman::AliasProcessor
17
17
  @current_class = @current_module = @current_method = nil
18
18
  end
19
19
 
20
+ def process_controller name, src
21
+ if not node_type? src, :class
22
+ Brakeman.debug "#{name} is not a class, it's a #{src.node_type}"
23
+ return
24
+ else
25
+ @current_class = name
26
+ process_default src
27
+ end
28
+ end
29
+
20
30
  #Processes a class which is probably a controller.
31
+ #(This method should be retired - only classes should ever be processed
32
+ # and @current_module will never be set, leading to inaccurate class names)
21
33
  def process_class exp
22
34
  @current_class = class_name(exp[1])
23
35
  if @current_module
24
- @current_class = (@current_module + "::" + @current_class.to_s).to_sym
36
+ @current_class = ("#@current_module::#@current_class").to_sym
25
37
  end
26
38
 
27
39
  process_default exp
@@ -101,7 +113,7 @@ class Brakeman::ControllerAliasProcessor < Brakeman::AliasProcessor
101
113
  processor = Brakeman::AliasProcessor.new @tracker
102
114
  processor.process_safely(method[3])
103
115
 
104
- ivars = processor.only_ivars.all
116
+ ivars = processor.only_ivars(:include_request_vars).all
105
117
 
106
118
  @tracker.filter_cache[[filter[:controller], name]] = ivars
107
119
 
@@ -130,7 +130,13 @@ class Brakeman::ControllerProcessor < Brakeman::BaseProcessor
130
130
  name = exp[2]
131
131
 
132
132
  if exp[1].node_type == :self
133
- target = @controller[:name]
133
+ if @controller
134
+ target = @controller[:name]
135
+ elsif @current_module
136
+ target = @current_module
137
+ else
138
+ target = nil
139
+ end
134
140
  else
135
141
  target = class_name exp[1]
136
142
  end
@@ -44,7 +44,7 @@ class Brakeman::ErbTemplateProcessor < Brakeman::TemplateProcessor
44
44
  end
45
45
  elsif target == nil and method == :render
46
46
  exp[3] = process(exp[3])
47
- make_render exp
47
+ make_render_in_view exp
48
48
  else
49
49
  args = exp[3] = process(exp[3])
50
50
  call = Sexp.new :call, target, method, args
@@ -41,7 +41,7 @@ class Brakeman::ErubisTemplateProcessor < Brakeman::TemplateProcessor
41
41
  end
42
42
  elsif target == nil and method == :render
43
43
  exp[3] = process exp[3]
44
- make_render exp
44
+ make_render_in_view exp
45
45
  else
46
46
  args = exp[3] = process(exp[3])
47
47
  call = Sexp.new :call, target, method, args
@@ -92,7 +92,7 @@ class Brakeman::HamlTemplateProcessor < Brakeman::TemplateProcessor
92
92
  elsif target == nil and method == :render
93
93
  #Process call to render()
94
94
  exp[3] = process exp[3]
95
- make_render exp
95
+ make_render_in_view exp
96
96
  else
97
97
  args = process exp[3]
98
98
  call = Sexp.new :call, target, method, args
@@ -3,9 +3,19 @@ module Brakeman::ProcessorHelper
3
3
 
4
4
  #Sets the current module.
5
5
  def process_module exp
6
- @current_module = class_name(exp[1]).to_s
7
- process exp[2]
8
- @current_module = nil
6
+ module_name = class_name(exp[1]).to_s
7
+ prev_module = @current_module
8
+
9
+ if prev_module
10
+ @current_module = "#{prev_module}::#{module_name}"
11
+ else
12
+ @current_module = module_name
13
+ end
14
+
15
+ process exp[2]
16
+
17
+ @current_module = prev_module
18
+
9
19
  exp
10
20
  end
11
21
 
@@ -11,8 +11,13 @@ module Brakeman::RenderHelper
11
11
  when :action
12
12
  process_action exp[2][1], exp[3]
13
13
  when :default
14
- process_template template_name, exp[3]
15
- when :partial
14
+ begin
15
+ process_template template_name, exp[3]
16
+ rescue ArgumentError => e
17
+ Brakeman.debug "Problem processing render: #{exp}"
18
+ raise e
19
+ end
20
+ when :partial, :layout
16
21
  process_partial exp[2], exp[3]
17
22
  when :nothing
18
23
  end
@@ -58,7 +63,7 @@ module Brakeman::RenderHelper
58
63
  return
59
64
  end
60
65
 
61
- template_env = only_ivars
66
+ template_env = only_ivars(:include_request_vars)
62
67
 
63
68
  #Hash the environment and the source of the template to avoid
64
69
  #pointlessly processing templates, which can become prohibitively
@@ -117,7 +122,7 @@ module Brakeman::RenderHelper
117
122
  #Run source through AliasProcessor with instance variables from the
118
123
  #current environment.
119
124
  #TODO: Add in :locals => { ... } to environment
120
- src = Brakeman::TemplateAliasProcessor.new(@tracker, template).process_safely(template[:src], template_env)
125
+ src = Brakeman::TemplateAliasProcessor.new(@tracker, template, called_from).process_safely(template[:src], template_env)
121
126
 
122
127
  #Run alias-processed src through the template processor to pull out
123
128
  #information and outputs.
@@ -9,14 +9,19 @@ class Brakeman::TemplateAliasProcessor < Brakeman::AliasProcessor
9
9
 
10
10
  FORM_METHODS = Set[:form_for, :remote_form_for, :form_remote_for]
11
11
 
12
- def initialize tracker, template
13
- super()
14
- @tracker = tracker
12
+ def initialize tracker, template, called_from = nil
13
+ super tracker
15
14
  @template = template
15
+ @called_from = called_from
16
16
  end
17
17
 
18
18
  #Process template
19
19
  def process_template name, args
20
+ if @called_from and @called_from.match(/Template:#{Regexp.escape name}$/)
21
+ Brakeman.debug "Skipping circular render from #{@template[:name]} to #{name}"
22
+ return
23
+ end
24
+
20
25
  super name, args, "Template:#{@template[:name]}"
21
26
  end
22
27
 
@@ -117,6 +117,8 @@ class Brakeman::Rescanner < Brakeman::Scanner
117
117
  end
118
118
 
119
119
  def rescan_template path
120
+ return unless path.match KNOWN_TEMPLATE_EXTENSIONS
121
+
120
122
  template_name = template_path_to_name(path)
121
123
 
122
124
  tracker.reset_template template_name
@@ -13,26 +13,21 @@ begin
13
13
  require 'erb'
14
14
  require 'erubis'
15
15
  require 'brakeman/processor'
16
+ require 'brakeman/parsers/rails2_erubis'
17
+ require 'brakeman/parsers/rails2_xss_plugin_erubis'
18
+ require 'brakeman/parsers/rails3_erubis'
16
19
  rescue LoadError => e
17
20
  $stderr.puts e.message
18
21
  $stderr.puts "Please install the appropriate dependency."
19
22
  exit
20
23
  end
21
24
 
22
- #Erubis processor which ignores any output which is plain text.
23
- class Brakeman::ScannerErubis < Erubis::Eruby
24
- include Erubis::NoTextEnhancer
25
- end
26
-
27
- class Brakeman::ErubisEscape < Brakeman::ScannerErubis
28
- include Erubis::EscapeEnhancer
29
- end
30
-
31
25
  #Scans the Rails application.
32
26
  class Brakeman::Scanner
33
27
  attr_reader :options
34
28
 
35
29
  RUBY_1_9 = !!(RUBY_VERSION =~ /^1\.9/)
30
+ KNOWN_TEMPLATE_EXTENSIONS = /.*\.(erb|haml|rhtml)$/
36
31
 
37
32
  #Pass in path to the root of the Rails application
38
33
  def initialize options, processor = nil
@@ -71,15 +66,15 @@ class Brakeman::Scanner
71
66
  process_initializers
72
67
  Brakeman.notify "Processing libs..."
73
68
  process_libs
74
- Brakeman.notify "Processing routes... "
69
+ Brakeman.notify "Processing routes... "
75
70
  process_routes
76
- Brakeman.notify "Processing templates... "
71
+ Brakeman.notify "Processing templates... "
77
72
  process_templates
78
- Brakeman.notify "Processing models... "
73
+ Brakeman.notify "Processing models... "
79
74
  process_models
80
- Brakeman.notify "Processing controllers... "
75
+ Brakeman.notify "Processing controllers... "
81
76
  process_controllers
82
- Brakeman.notify "Indexing call sites... "
77
+ Brakeman.notify "Indexing call sites... "
83
78
  index_call_sites
84
79
  tracker
85
80
  end
@@ -215,7 +210,7 @@ class Brakeman::Scanner
215
210
  controller_files = Dir.glob(@app_path + "/controllers/**/*.rb").sort
216
211
  controller_files.reject! { |f| @skip_files.match f } if @skip_files
217
212
 
218
- total = controller_files.length * 2
213
+ total = controller_files.length
219
214
  current = 0
220
215
 
221
216
  controller_files.each do |f|
@@ -240,7 +235,7 @@ class Brakeman::Scanner
240
235
  current += 1
241
236
  end
242
237
 
243
- @processor.process_controller_alias controller[:src]
238
+ @processor.process_controller_alias name, controller[:src]
244
239
  end
245
240
 
246
241
  #No longer need these processed filter methods
@@ -298,7 +293,7 @@ class Brakeman::Scanner
298
293
  end
299
294
 
300
295
  def process_template path
301
- type = path.match(/.*\.(erb|haml|rhtml)$/)[1].to_sym
296
+ type = path.match(KNOWN_TEMPLATE_EXTENSIONS)[1].to_sym
302
297
  type = :erb if type == :rhtml
303
298
  name = template_path_to_name path
304
299
  text = File.read path
@@ -308,9 +303,9 @@ class Brakeman::Scanner
308
303
  if tracker.config[:escape_html]
309
304
  type = :erubis
310
305
  if options[:rails3]
311
- src = Brakeman::Rails3XSSErubis.new(text).src
306
+ src = Brakeman::Rails3Erubis.new(text).src
312
307
  else
313
- src = Brakeman::Rails2XSSErubis.new(text).src
308
+ src = Brakeman::Rails2XSSPluginErubis.new(text).src
314
309
  end
315
310
  elsif tracker.config[:erubis]
316
311
  type = :erubis
@@ -353,7 +348,7 @@ class Brakeman::Scanner
353
348
  #
354
349
  #Adds the processed models to tracker.models
355
350
  def process_models
356
- model_files = Dir.glob(@app_path + "/models/*.rb").sort
351
+ model_files = Dir.glob(@app_path + "/models/**/*.rb").sort
357
352
  model_files.reject! { |f| @skip_files.match f } if @skip_files
358
353
 
359
354
  total = model_files.length
@@ -389,111 +384,3 @@ class Brakeman::Scanner
389
384
  @ruby_parser.new.parse input
390
385
  end
391
386
  end
392
-
393
- #This is from Rails 3 version of the Erubis handler
394
- class Brakeman::Rails3XSSErubis < ::Erubis::Eruby
395
-
396
- def add_preamble(src)
397
- # src << "_buf = ActionView::SafeBuffer.new;\n"
398
- end
399
-
400
- #This is different from Rails 3 - fixes some line number issues
401
- def add_text(src, text)
402
- if text == "\n"
403
- src << "\n"
404
- elsif text.include? "\n"
405
- lines = text.split("\n")
406
- if text.match(/\n\z/)
407
- lines.each do |line|
408
- src << "@output_buffer << ('" << escape_text(line) << "'.html_safe!);\n"
409
- end
410
- else
411
- lines[0..-2].each do |line|
412
- src << "@output_buffer << ('" << escape_text(line) << "'.html_safe!);\n"
413
- end
414
-
415
- src << "@output_buffer << ('" << escape_text(lines.last) << "'.html_safe!);"
416
- end
417
- else
418
- src << "@output_buffer << ('" << escape_text(text) << "'.html_safe!);"
419
- end
420
- end
421
-
422
- BLOCK_EXPR = /\s+(do|\{)(\s*\|[^|]*\|)?\s*\Z/
423
-
424
- def add_expr_literal(src, code)
425
- if code =~ BLOCK_EXPR
426
- src << '@output_buffer.append= ' << code
427
- else
428
- src << '@output_buffer.append= (' << code << ');'
429
- end
430
- end
431
-
432
- def add_stmt(src, code)
433
- if code =~ BLOCK_EXPR
434
- src << '@output_buffer.append_if_string= ' << code
435
- else
436
- super
437
- end
438
- end
439
-
440
- def add_expr_escaped(src, code)
441
- if code =~ BLOCK_EXPR
442
- src << "@output_buffer.safe_append= " << code
443
- else
444
- src << "@output_buffer.safe_concat(" << code << ");"
445
- end
446
- end
447
-
448
- #Add code to output buffer.
449
- def add_postamble(src)
450
- # src << '_buf.to_s'
451
- end
452
- end
453
-
454
- #This is from the rails_xss plugin for Rails 2
455
- class Brakeman::Rails2XSSErubis < ::Erubis::Eruby
456
- def add_preamble(src)
457
- #src << "@output_buffer = ActiveSupport::SafeBuffer.new;"
458
- end
459
-
460
- #This is different from rails_xss - fixes some line number issues
461
- def add_text(src, text)
462
- if text == "\n"
463
- src << "\n"
464
- elsif text.include? "\n"
465
- lines = text.split("\n")
466
- if text.match(/\n\z/)
467
- lines.each do |line|
468
- src << "@output_buffer.safe_concat('" << escape_text(line) << "');\n"
469
- end
470
- else
471
- lines[0..-2].each do |line|
472
- src << "@output_buffer.safe_concat('" << escape_text(line) << "');\n"
473
- end
474
-
475
- src << "@output_buffer.safe_concat('" << escape_text(lines.last) << "');"
476
- end
477
- else
478
- src << "@output_buffer.safe_concat('" << escape_text(text) << "');"
479
- end
480
- end
481
-
482
- BLOCK_EXPR = /\s+(do|\{)(\s*\|[^|]*\|)?\s*\Z/
483
-
484
- def add_expr_literal(src, code)
485
- if code =~ BLOCK_EXPR
486
- src << "@output_buffer.safe_concat((" << $1 << ").to_s);"
487
- else
488
- src << '@output_buffer << ((' << code << ').to_s);'
489
- end
490
- end
491
-
492
- def add_expr_escaped(src, code)
493
- src << '@output_buffer << ' << escaped_expr(code) << ';'
494
- end
495
-
496
- def add_postamble(src)
497
- #src << '@output_buffer.to_s'
498
- end
499
- end
@@ -80,6 +80,23 @@ module Brakeman::Util
80
80
  hash
81
81
  end
82
82
 
83
+ #Get value from hash using key.
84
+ #
85
+ #If _key_ is a Symbol, it will be converted to a Sexp(:lit, key).
86
+ def hash_access hash, key
87
+ if key.is_a? Symbol
88
+ key = Sexp.new(:lit, key)
89
+ end
90
+
91
+ hash_iterate hash do |k, v|
92
+ if k == key
93
+ return v
94
+ end
95
+ end
96
+
97
+ nil
98
+ end
99
+
83
100
  #Adds params, session, and cookies to environment
84
101
  #so they can be replaced by their respective Sexps.
85
102
  def set_env_defaults
@@ -187,6 +204,13 @@ module Brakeman::Util
187
204
  call? exp and (exp == REQUEST_ENV or exp[1] == REQUEST_ENV)
188
205
  end
189
206
 
207
+ #Check if exp is params, cookies, or request_env
208
+ def request_value? exp
209
+ params? exp or
210
+ cookies? exp or
211
+ request_env? exp
212
+ end
213
+
190
214
  #Check if _exp_ is a Sexp.
191
215
  def sexp? exp
192
216
  exp.is_a? Sexp
@@ -1,3 +1,3 @@
1
1
  module Brakeman
2
- Version = "1.5.2"
2
+ Version = "1.5.3"
3
3
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brakeman
3
3
  version: !ruby/object:Gem::Version
4
- hash: 7
4
+ hash: 5
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 5
9
- - 2
10
- version: 1.5.2
9
+ - 3
10
+ version: 1.5.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Justin Collins
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-03-22 00:00:00 Z
18
+ date: 2012-04-10 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: activesupport
@@ -133,6 +133,7 @@ files:
133
133
  - WARNING_TYPES
134
134
  - FEATURES
135
135
  - README.md
136
+ - lib/brakeman/brakeman.rake
136
137
  - lib/ruby_parser/ruby18_parser.rb
137
138
  - lib/ruby_parser/ruby_parser_extras.rb
138
139
  - lib/ruby_parser/bm_sexp.rb
@@ -193,12 +194,16 @@ files:
193
194
  - lib/brakeman/checks/check_file_access.rb
194
195
  - lib/brakeman/checks/check_response_splitting.rb
195
196
  - lib/brakeman/checks/check_basic_auth.rb
197
+ - lib/brakeman/checks/check_send.rb
196
198
  - lib/brakeman/checks/check_redirect.rb
197
199
  - lib/brakeman/checks/check_forgery_setting.rb
198
200
  - lib/brakeman/checks/check_render.rb
199
201
  - lib/brakeman/tracker.rb
200
202
  - lib/brakeman/util.rb
201
203
  - lib/brakeman/report.rb
204
+ - lib/brakeman/parsers/rails3_erubis.rb
205
+ - lib/brakeman/parsers/rails2_xss_plugin_erubis.rb
206
+ - lib/brakeman/parsers/rails2_erubis.rb
202
207
  - lib/brakeman/version.rb
203
208
  - lib/brakeman/call_index.rb
204
209
  - lib/brakeman/options.rb