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
@@ -92,7 +92,7 @@ module Brakeman::RenderHelper
92
92
 
93
93
  if hash? options[:locals]
94
94
  hash_iterate options[:locals] do |key, value|
95
- template_env[Sexp.new(:call, nil, key.value, Sexp.new(:arglist))] = value
95
+ template_env[Sexp.new(:call, nil, key.value)] = value
96
96
  end
97
97
  end
98
98
 
@@ -111,7 +111,7 @@ module Brakeman::RenderHelper
111
111
 
112
112
  collection = get_class_target(options[:collection]) || Brakeman::Tracker::UNKNOWN_MODEL
113
113
 
114
- template_env[Sexp.new(:call, nil, variable, Sexp.new(:arglist))] = Sexp.new(:call, Sexp.new(:const, collection), :new, Sexp.new(:arglist))
114
+ template_env[Sexp.new(:call, nil, variable)] = Sexp.new(:call, Sexp.new(:const, collection), :new)
115
115
  end
116
116
 
117
117
  #Set original_line for values so it is clear
@@ -49,7 +49,7 @@ class Brakeman::LibraryProcessor < Brakeman::BaseProcessor
49
49
  @tracker.libs[name] = @current_class
50
50
  end
51
51
 
52
- exp.body = process exp.body
52
+ exp.body = process_all! exp.body
53
53
 
54
54
  if outer_class
55
55
  @current_class = outer_class
@@ -86,7 +86,7 @@ class Brakeman::LibraryProcessor < Brakeman::BaseProcessor
86
86
  @tracker.libs[name] = @current_module
87
87
  end
88
88
 
89
- exp.body = process exp.body
89
+ exp.body = process_all! exp.body
90
90
 
91
91
  if outer_class
92
92
  @current_module = outer_class
@@ -19,7 +19,7 @@ class Brakeman::ModelProcessor < Brakeman::BaseProcessor
19
19
  process src
20
20
  end
21
21
 
22
- #s(:class, NAME, PARENT, s(:scope ...))
22
+ #s(:class, NAME, PARENT, BODY)
23
23
  def process_class exp
24
24
  name = class_name exp.class_name
25
25
 
@@ -44,9 +44,9 @@ class Brakeman::ModelProcessor < Brakeman::BaseProcessor
44
44
  :associations => {},
45
45
  :file => @file_name }
46
46
  @tracker.models[@model[:name]] = @model
47
- res = process exp.body
47
+ exp.body = process_all! exp.body
48
48
  @model = nil
49
- res
49
+ exp
50
50
  end
51
51
  end
52
52
 
@@ -60,12 +60,12 @@ class Brakeman::ModelProcessor < Brakeman::BaseProcessor
60
60
  end
61
61
 
62
62
  method = exp.method
63
- args = exp.args
63
+ first_arg = exp.first_arg
64
64
 
65
65
  #Methods called inside class definition
66
66
  #like attr_* and other settings
67
67
  if @current_method.nil? and target.nil?
68
- if args.empty?
68
+ if first_arg.nil?
69
69
  case method
70
70
  when :private, :protected, :public
71
71
  @visibility = method
@@ -77,11 +77,15 @@ class Brakeman::ModelProcessor < Brakeman::BaseProcessor
77
77
  else
78
78
  case method
79
79
  when :include
80
- @model[:includes] << class_name(args.first) if @model
80
+ @model[:includes] << class_name(first_arg) if @model
81
81
  when :attr_accessible
82
82
  @model[:attr_accessible] ||= []
83
- args = args.map do |e|
84
- e[1]
83
+ args = []
84
+
85
+ exp.each_arg do |e|
86
+ if node_type? e, :lit
87
+ args << e.value
88
+ end
85
89
  end
86
90
 
87
91
  @model[:attr_accessible].concat args
@@ -92,14 +96,14 @@ class Brakeman::ModelProcessor < Brakeman::BaseProcessor
92
96
  @model[:associations][method].concat exp.args
93
97
  else
94
98
  @model[:options][method] ||= []
95
- @model[:options][method] << exp.arglist
99
+ @model[:options][method] << exp.arglist.line(exp.line)
96
100
  end
97
101
  end
98
102
  end
99
103
  end
100
104
  ignore
101
105
  else
102
- call = Sexp.new :call, target, method, process(exp.arglist)
106
+ call = make_call target, method, process_all!(exp.args)
103
107
  call.line(exp.line)
104
108
  call
105
109
  end
@@ -111,7 +115,7 @@ class Brakeman::ModelProcessor < Brakeman::BaseProcessor
111
115
  name = exp.method_name
112
116
 
113
117
  @current_method = name
114
- res = Sexp.new :methdef, name, exp[2], process(exp.body.value)
118
+ res = Sexp.new :methdef, name, exp.formal_args, *process_all!(exp.body)
115
119
  res.line(exp.line)
116
120
  @current_method = nil
117
121
  if @model
@@ -133,7 +137,7 @@ class Brakeman::ModelProcessor < Brakeman::BaseProcessor
133
137
  end
134
138
 
135
139
  @current_method = name
136
- res = Sexp.new :selfdef, target, name, exp[3], process(exp.body.value)
140
+ res = Sexp.new :selfdef, target, name, exp.formal_args, *process_all!(exp.body)
137
141
  res.line(exp.line)
138
142
  @current_method = nil
139
143
  if @model
@@ -14,6 +14,7 @@ class Brakeman::OutputProcessor < Ruby2Ruby
14
14
  end
15
15
 
16
16
  alias process_safely format
17
+ alias process_methdef process_defn
17
18
 
18
19
  def process exp
19
20
  begin
@@ -100,7 +101,7 @@ class Brakeman::OutputProcessor < Ruby2Ruby
100
101
 
101
102
  def process_call_with_block exp
102
103
  call = process exp[0]
103
- block = process exp[1] if exp[1]
104
+ block = process_rlist exp[2..-1]
104
105
  out = "#{call} do\n #{block}\n end"
105
106
  exp.clear
106
107
  out
@@ -1,6 +1,7 @@
1
1
  require 'set'
2
2
  require 'brakeman/processors/alias_processor'
3
3
  require 'brakeman/processors/lib/render_helper'
4
+ require 'brakeman/tracker'
4
5
 
5
6
  #Processes aliasing in templates.
6
7
  #Handles calls to +render+.
@@ -37,32 +38,35 @@ class Brakeman::TemplateAliasProcessor < Brakeman::AliasProcessor
37
38
  name
38
39
  end
39
40
 
41
+ UNKNOWN_MODEL_CALL = Sexp.new(:call, Sexp.new(:const, Brakeman::Tracker::UNKNOWN_MODEL), :new)
42
+ FORM_BUILDER_CALL = Sexp.new(:call, Sexp.new(:const, :FormBuilder), :new)
43
+
40
44
  #Looks for form methods and iterating over collections of Models
41
45
  def process_call_with_block exp
42
46
  process_default exp
43
-
47
+
44
48
  call = exp.block_call
45
49
 
46
50
  if call? call
47
51
  target = call.target
48
52
  method = call.method
49
- args = exp.block_args
53
+ arg = exp.block_args.first_param
50
54
  block = exp.block
51
55
 
52
56
  #Check for e.g. Model.find.each do ... end
53
- if method == :each and args and block and model = get_model_target(target)
54
- if node_type? args, :lasgn
57
+ if method == :each and arg and block and model = get_model_target(target)
58
+ if arg.is_a? Symbol
55
59
  if model == target.target
56
- env[Sexp.new(:lvar, args.lhs)] = Sexp.new(:call, model, :new, Sexp.new(:arglist))
60
+ env[Sexp.new(:lvar, arg)] = Sexp.new(:call, model, :new)
57
61
  else
58
- env[Sexp.new(:lvar, args.lhs)] = Sexp.new(:call, Sexp.new(:const, Brakeman::Tracker::UNKNOWN_MODEL), :new, Sexp.new(:arglist))
62
+ env[Sexp.new(:lvar, arg)] = UNKNOWN_MODEL_CALL
59
63
  end
60
64
 
61
65
  process block if sexp? block
62
66
  end
63
67
  elsif FORM_METHODS.include? method
64
- if node_type? args, :lasgn
65
- env[Sexp.new(:lvar, args.lhs)] = Sexp.new(:call, Sexp.new(:const, :FormBuilder), :new, Sexp.new(:arglist))
68
+ if arg.is_a? Symbol
69
+ env[Sexp.new(:lvar, arg)] = FORM_BUILDER_CALL
66
70
 
67
71
  process block if sexp? block
68
72
  end
@@ -40,7 +40,8 @@ class Brakeman::Report
40
40
  "<span class='med-confidence'>Medium</span>",
41
41
  "<span class='weak-confidence'>Weak</span>" ]
42
42
 
43
- def initialize tracker
43
+ def initialize(app_tree, tracker)
44
+ @app_tree = app_tree
44
45
  @tracker = tracker
45
46
  @checks = tracker.checks
46
47
  @element_id = 0 #Used for HTML ids
@@ -158,7 +159,7 @@ class Brakeman::Report
158
159
  end
159
160
 
160
161
  return nil if warnings.empty?
161
-
162
+
162
163
  stabilizer = 0
163
164
  warnings = warnings.sort_by{|row| stabilizer += 1; [row["Confidence"], row["Warning Type"], row["Template"], stabilizer]}
164
165
  if html
@@ -232,7 +233,7 @@ class Brakeman::Report
232
233
  end
233
234
 
234
235
  return nil if warnings.empty?
235
-
236
+
236
237
  stabilizer = 0
237
238
  warnings = warnings.sort_by{|row| stabilizer +=1; [row["Confidence"], row["Warning Type"], row["Controller"], stabilizer]}
238
239
 
@@ -318,7 +319,7 @@ class Brakeman::Report
318
319
  else
319
320
  output = ''
320
321
  template_rows.each do |template|
321
- output << template.first.to_s << "\n\n"
322
+ output << template.first.to_s << "\n\n"
322
323
  table = Terminal::Table.new(:headings => ['Output']) do |t|
323
324
  # template[1] is an array of calls
324
325
  template[1].each do |v|
@@ -392,7 +393,7 @@ class Brakeman::Report
392
393
  res = generate_controller_warnings
393
394
  out << "\n\n\nController Warnings:\n\n" << truncate_table(res.to_s) if res
394
395
 
395
- res = generate_model_warnings
396
+ res = generate_model_warnings
396
397
  out << "\n\n\nModel Warnings:\n\n" << truncate_table(res.to_s) if res
397
398
 
398
399
  res = generate_template_warnings
@@ -404,8 +405,8 @@ class Brakeman::Report
404
405
 
405
406
  #Generate CSV output
406
407
  def to_csv
407
- output = csv_header
408
- output << "\nSUMMARY\n"
408
+ output = csv_header
409
+ output << "\nSUMMARY\n"
409
410
 
410
411
  output << table_to_csv(generate_overview) << "\n"
411
412
 
@@ -437,7 +438,7 @@ class Brakeman::Report
437
438
  output << table_to_csv(res) << "\n" if res
438
439
 
439
440
  output << "Model Warnings\n"
440
- res = generate_model_warnings
441
+ res = generate_model_warnings
441
442
  output << table_to_csv(res) << "\n" if res
442
443
 
443
444
  res = generate_template_warnings
@@ -475,7 +476,17 @@ class Brakeman::Report
475
476
 
476
477
  #Generate header for text output
477
478
  def text_header
478
- "\n+BRAKEMAN REPORT+\n\nApplication path: #{File.expand_path tracker.options[:app_path]}\nRails version: #{rails_version}\nGenerated at #{Time.now}\nChecks run: #{checks.checks_run.sort.join(", ")}\n"
479
+ <<-HEADER
480
+
481
+ +BRAKEMAN REPORT+
482
+
483
+ Application path: #{File.expand_path tracker.options[:app_path]}
484
+ Rails version: #{rails_version}
485
+ Brakeman version: #{Brakeman::Version}
486
+ Started at #{tracker.start_time}
487
+ Duration: #{tracker.duration} seconds
488
+ Checks run: #{checks.checks_run.sort.join(", ")}
489
+ HEADER
479
490
  end
480
491
 
481
492
  #Generate header for CSV output
@@ -532,11 +543,11 @@ class Brakeman::Report
532
543
 
533
544
  #Generate HTML for warnings, including context show/hidden via Javascript
534
545
  def with_context warning, message
535
- context = context_for warning
546
+ context = context_for(@app_tree, warning)
536
547
  full_message = nil
537
548
 
538
549
  if tracker.options[:message_limit] and
539
- tracker.options[:message_limit] > 0 and
550
+ tracker.options[:message_limit] > 0 and
540
551
  message.length > tracker.options[:message_limit]
541
552
 
542
553
  full_message = html_message(warning, message)
@@ -647,12 +658,12 @@ class Brakeman::Report
647
658
  else
648
659
  w.code = ""
649
660
  end
650
- w.context = context_for(w).join("\n")
661
+ w.context = context_for(@app_tree, w).join("\n")
651
662
  end
652
663
  end
653
664
 
654
665
  report[:config] = tracker.config
655
-
666
+
656
667
  report
657
668
  end
658
669
 
@@ -670,7 +681,10 @@ class Brakeman::Report
670
681
  :app_path => File.expand_path(tracker.options[:app_path]),
671
682
  :rails_version => rails_version,
672
683
  :security_warnings => all_warnings.length,
673
- :timestamp => Time.now.to_s,
684
+ :start_time => tracker.start_time.to_s,
685
+ :end_time => tracker.end_time.to_s,
686
+ :timestamp => tracker.end_time.to_s,
687
+ :duration => tracker.duration,
674
688
  :checks_performed => checks.checks_run.sort,
675
689
  :number_of_controllers =>tracker.controllers.length,
676
690
  # ignore the "fake" model
@@ -12,7 +12,7 @@ class Brakeman::Rescanner < Brakeman::Scanner
12
12
  def initialize options, processor, changed_files
13
13
  super(options, processor)
14
14
 
15
- @paths = changed_files.map {|f| File.expand_path f, tracker.options[:app_path] }
15
+ @paths = changed_files.map {|f| @app_tree.expand_path(f) }
16
16
  @old_results = tracker.checks #Old warnings from previous scan
17
17
  @changes = nil #True if files had to be rescanned
18
18
  @reindex = Set.new
@@ -66,7 +66,7 @@ class Brakeman::Rescanner < Brakeman::Scanner
66
66
  def rescan_file path, type = nil
67
67
  type ||= file_type path
68
68
 
69
- unless File.exist? path
69
+ unless @app_tree.path_exists?(path)
70
70
  return rescan_deleted_file path, type
71
71
  end
72
72
 
@@ -128,7 +128,7 @@ class Brakeman::Rescanner < Brakeman::Scanner
128
128
  end
129
129
 
130
130
  def rescan_template path
131
- return unless path.match KNOWN_TEMPLATE_EXTENSIONS and File.exist? path
131
+ return unless path.match KNOWN_TEMPLATE_EXTENSIONS and @app_tree.path_exists?(path)
132
132
 
133
133
  template_name = template_path_to_name(path)
134
134
 
@@ -177,7 +177,7 @@ class Brakeman::Rescanner < Brakeman::Scanner
177
177
  def rescan_model path
178
178
  num_models = tracker.models.length
179
179
  tracker.reset_model path
180
- process_model path if File.exists? path
180
+ process_model path if @app_tree.path_exists?(path)
181
181
 
182
182
  #Only need to rescan other things if a model is added or removed
183
183
  if num_models != tracker.models.length
@@ -190,7 +190,7 @@ class Brakeman::Rescanner < Brakeman::Scanner
190
190
  end
191
191
 
192
192
  def rescan_lib path
193
- process_lib path if File.exists? path
193
+ process_lib path if @app_tree.path_exists?(path)
194
194
 
195
195
  lib = nil
196
196
 
@@ -1,13 +1,7 @@
1
1
  require 'rubygems'
2
2
  begin
3
- if RUBY_VERSION =~ /^1\.9/
4
- #Load our own version of ruby_parser :'(
5
- require 'ruby_parser/ruby_parser.rb'
6
- else
7
- require 'ruby_parser'
8
- require 'ruby_parser/bm_sexp.rb'
9
- end
10
-
3
+ require 'ruby_parser'
4
+ require 'ruby_parser/bm_sexp.rb'
11
5
  require 'ruby_parser/bm_sexp_processor.rb'
12
6
 
13
7
  require 'haml'
@@ -15,6 +9,7 @@ begin
15
9
  require 'erb'
16
10
  require 'erubis'
17
11
  require 'brakeman/processor'
12
+ require 'brakeman/app_tree'
18
13
  require 'brakeman/parsers/rails2_erubis'
19
14
  require 'brakeman/parsers/rails2_xss_plugin_erubis'
20
15
  require 'brakeman/parsers/rails3_erubis'
@@ -34,23 +29,19 @@ class Brakeman::Scanner
34
29
  #Pass in path to the root of the Rails application
35
30
  def initialize options, processor = nil
36
31
  @options = options
37
- @report_progress = options[:report_progress]
38
- @path = options[:app_path]
39
- @app_path = File.join(@path, "app")
40
- @processor = processor || Brakeman::Processor.new(options)
41
- @skip_files = nil
42
-
43
- #Convert files into Regexp for matching
44
- if options[:skip_files]
45
- list = "(?:" << options[:skip_files].map { |f| Regexp.escape f }.join("|") << ")$"
46
- @skip_files = Regexp.new(list)
32
+ @app_tree = Brakeman::AppTree.from_options(options)
33
+
34
+ if !@app_tree.root || !@app_tree.exists?("app")
35
+ abort("Please supply the path to a Rails application.")
47
36
  end
48
37
 
49
- if RUBY_1_9
50
- @ruby_parser = ::Ruby19Parser
51
- else
52
- @ruby_parser = ::RubyParser
38
+ if @app_tree.exists?("script/rails")
39
+ options[:rails3] = true
40
+ Brakeman.notify "[Notice] Detected Rails 3 application"
53
41
  end
42
+
43
+ @ruby_parser = ::RubyParser
44
+ @processor = processor || Brakeman::Processor.new(@app_tree, options)
54
45
  end
55
46
 
56
47
  #Returns the Tracker generated from the scan
@@ -93,7 +84,7 @@ class Brakeman::Scanner
93
84
  process_config_file "gems.rb"
94
85
  end
95
86
 
96
- if File.exists? "#@path/vendor/plugins/rails_xss" or
87
+ if @app_tree.exists?("vendor/plugins/rails_xss") or
97
88
  options[:rails3] or options[:escape_html]
98
89
 
99
90
  tracker.config[:escape_html] = true
@@ -102,8 +93,10 @@ class Brakeman::Scanner
102
93
  end
103
94
 
104
95
  def process_config_file file
105
- if File.exists? "#@path/config/#{file}"
106
- @processor.process_config(parse_ruby(File.read("#@path/config/#{file}")))
96
+ path = "config/#{file}"
97
+
98
+ if @app_tree.exists?(path)
99
+ @processor.process_config(parse_ruby(@app_tree.read(path)))
107
100
  end
108
101
 
109
102
  rescue Exception => e
@@ -115,11 +108,11 @@ class Brakeman::Scanner
115
108
 
116
109
  #Process Gemfile
117
110
  def process_gems
118
- if File.exists? "#@path/Gemfile"
119
- if File.exists? "#@path/Gemfile.lock"
120
- @processor.process_gems(parse_ruby(File.read("#@path/Gemfile")), File.read("#@path/Gemfile.lock"))
111
+ if @app_tree.exists? "Gemfile"
112
+ if @app_tree.exists? "Gemfile.lock"
113
+ @processor.process_gems(parse_ruby(@app_tree.read("Gemfile")), @app_tree.read("Gemfile.lock"))
121
114
  else
122
- @processor.process_gems(parse_ruby(File.read("#@path/Gemfile")))
115
+ @processor.process_gems(parse_ruby(@app_tree.read("Gemfile")))
123
116
  end
124
117
  end
125
118
  rescue Exception => e
@@ -131,10 +124,7 @@ class Brakeman::Scanner
131
124
  #
132
125
  #Adds parsed information to tracker.initializers
133
126
  def process_initializers
134
- initializer_files = Dir.glob(@path + "/config/initializers/**/*.rb").sort
135
- initializer_files.reject! { |f| @skip_files.match f } if @skip_files
136
-
137
- initializer_files.each do |f|
127
+ @app_tree.initializer_paths.each do |f|
138
128
  process_initializer f
139
129
  end
140
130
  end
@@ -142,7 +132,7 @@ class Brakeman::Scanner
142
132
  #Process an initializer
143
133
  def process_initializer path
144
134
  begin
145
- @processor.process_initializer(path, parse_ruby(File.read(path)))
135
+ @processor.process_initializer(path, parse_ruby(@app_tree.read_path(path)))
146
136
  rescue Racc::ParseError => e
147
137
  tracker.error e, "could not parse #{path}. There is probably a typo in the file. Test it with 'ruby_parse #{path}'"
148
138
  rescue Exception => e
@@ -159,19 +149,13 @@ class Brakeman::Scanner
159
149
  return
160
150
  end
161
151
 
162
- lib_files = Dir.glob(@path + "/lib/**/*.rb").sort
163
- lib_files.reject! { |f| @skip_files.match f } if @skip_files
164
-
165
- total = lib_files.length
152
+ total = @app_tree.lib_paths.length
166
153
  current = 0
167
154
 
168
- lib_files.each do |f|
155
+ @app_tree.lib_paths.each do |f|
169
156
  Brakeman.debug "Processing #{f}"
170
- if @report_progress
171
- $stderr.print " #{current}/#{total} files processed\r"
172
- current += 1
173
- end
174
-
157
+ report_progress(current, total)
158
+ current += 1
175
159
  process_lib f
176
160
  end
177
161
  end
@@ -179,7 +163,7 @@ class Brakeman::Scanner
179
163
  #Process a library
180
164
  def process_lib path
181
165
  begin
182
- @processor.process_lib parse_ruby(File.read(path)), path
166
+ @processor.process_lib parse_ruby(@app_tree.read_path(path)), path
183
167
  rescue Racc::ParseError => e
184
168
  tracker.error e, "could not parse #{path}. There is probably a typo in the file. Test it with 'ruby_parse #{path}'"
185
169
  rescue Exception => e
@@ -191,9 +175,9 @@ class Brakeman::Scanner
191
175
  #
192
176
  #Adds parsed information to tracker.routes
193
177
  def process_routes
194
- if File.exists? "#@path/config/routes.rb"
178
+ if @app_tree.exists?("config/routes.rb")
195
179
  begin
196
- @processor.process_routes parse_ruby(File.read("#@path/config/routes.rb"))
180
+ @processor.process_routes parse_ruby(@app_tree.read("config/routes.rb"))
197
181
  rescue Exception => e
198
182
  tracker.error e.exception(e.message + "\nWhile processing routes.rb"), e.backtrace
199
183
  Brakeman.notify "[Notice] Error while processing routes - assuming all public controller methods are actions."
@@ -208,19 +192,13 @@ class Brakeman::Scanner
208
192
  #
209
193
  #Adds processed controllers to tracker.controllers
210
194
  def process_controllers
211
- controller_files = Dir.glob(@app_path + "/controllers/**/*.rb").sort
212
- controller_files.reject! { |f| @skip_files.match f } if @skip_files
213
-
214
- total = controller_files.length
195
+ total = @app_tree.controller_paths.length
215
196
  current = 0
216
197
 
217
- controller_files.each do |f|
198
+ @app_tree.controller_paths.each do |f|
218
199
  Brakeman.debug "Processing #{f}"
219
- if @report_progress
220
- $stderr.print " #{current}/#{total} files processed\r"
221
- current += 1
222
- end
223
-
200
+ report_progress(current, total)
201
+ current += 1
224
202
  process_controller f
225
203
  end
226
204
 
@@ -231,11 +209,8 @@ class Brakeman::Scanner
231
209
 
232
210
  tracker.controllers.sort_by{|name| name.to_s}.each do |name, controller|
233
211
  Brakeman.debug "Processing #{name}"
234
- if @report_progress
235
- $stderr.print " #{current}/#{total} controllers processed\r"
236
- current += 1
237
- end
238
-
212
+ report_progress(current, total, "controllers")
213
+ current += 1
239
214
  @processor.process_controller_alias name, controller[:src]
240
215
  end
241
216
 
@@ -245,7 +220,7 @@ class Brakeman::Scanner
245
220
 
246
221
  def process_controller path
247
222
  begin
248
- @processor.process_controller(parse_ruby(File.read(path)), path)
223
+ @processor.process_controller(parse_ruby(@app_tree.read_path(path)), path)
249
224
  rescue Racc::ParseError => e
250
225
  tracker.error e, "could not parse #{path}. There is probably a typo in the file. Test it with 'ruby_parse #{path}'"
251
226
  rescue Exception => e
@@ -257,23 +232,15 @@ class Brakeman::Scanner
257
232
  #
258
233
  #Adds processed views to tracker.views
259
234
  def process_templates
260
-
261
- views_path = @app_path + "/views/**/*.{html.erb,html.haml,rhtml,js.erb}"
262
235
  $stdout.sync = true
263
- count = 0
264
236
 
265
- template_files = Dir.glob(views_path).sort
266
- template_files.reject! { |f| @skip_files.match f } if @skip_files
267
-
268
- total = template_files.length
237
+ count = 0
238
+ total = @app_tree.template_paths.length
269
239
 
270
- template_files.each do |path|
240
+ @app_tree.template_paths.each do |path|
271
241
  Brakeman.debug "Processing #{path}"
272
- if @report_progress
273
- $stderr.print " #{count}/#{total} files processed\r"
274
- count += 1
275
- end
276
-
242
+ report_progress(count, total)
243
+ count += 1
277
244
  process_template path
278
245
  end
279
246
 
@@ -284,11 +251,8 @@ class Brakeman::Scanner
284
251
 
285
252
  tracker.templates.keys.dup.sort_by{|name| name.to_s}.each do |name|
286
253
  Brakeman.debug "Processing #{name}"
287
- if @report_progress
288
- count += 1
289
- $stderr.print " #{count}/#{total} templates processed\r"
290
- end
291
-
254
+ report_progress(count, total, "templates")
255
+ count += 1
292
256
  @processor.process_template_alias tracker.templates[name]
293
257
  end
294
258
  end
@@ -297,7 +261,7 @@ class Brakeman::Scanner
297
261
  type = path.match(KNOWN_TEMPLATE_EXTENSIONS)[1].to_sym
298
262
  type = :erb if type == :rhtml
299
263
  name = template_path_to_name path
300
- text = File.read path
264
+ text = @app_tree.read_path path
301
265
 
302
266
  begin
303
267
  if type == :erb
@@ -349,27 +313,20 @@ class Brakeman::Scanner
349
313
  #
350
314
  #Adds the processed models to tracker.models
351
315
  def process_models
352
- model_files = Dir.glob(@app_path + "/models/**/*.rb").sort
353
- model_files.reject! { |f| @skip_files.match f } if @skip_files
354
-
355
- total = model_files.length
316
+ total = @app_tree.model_paths.length
356
317
  current = 0
357
318
 
358
- model_files.each do |f|
319
+ @app_tree.model_paths.each do |f|
359
320
  Brakeman.debug "Processing #{f}"
360
- if @report_progress
361
- $stderr.print " #{current}/#{total} files processed\r"
362
- current += 1
363
- end
364
-
321
+ report_progress(current, total)
322
+ current += 1
365
323
  process_model f
366
-
367
324
  end
368
325
  end
369
326
 
370
327
  def process_model path
371
328
  begin
372
- @processor.process_model(parse_ruby(File.read(path)), path)
329
+ @processor.process_model(parse_ruby(@app_tree.read_path(path)), path)
373
330
  rescue Racc::ParseError => e
374
331
  tracker.error e, "could not parse #{path}"
375
332
  rescue Exception => e
@@ -377,6 +334,11 @@ class Brakeman::Scanner
377
334
  end
378
335
  end
379
336
 
337
+ def report_progress(current, total, type = "files")
338
+ return unless @options[:report_progress]
339
+ $stderr.print " #{current}/#{total} #{type} processed\r"
340
+ end
341
+
380
342
  def index_call_sites
381
343
  tracker.index_call_sites
382
344
  end