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.
- data/README.md +3 -27
- data/lib/brakeman.rb +36 -38
- data/lib/brakeman/app_tree.rb +90 -0
- data/lib/brakeman/call_index.rb +5 -38
- data/lib/brakeman/checks.rb +11 -11
- data/lib/brakeman/checks/base_check.rb +53 -29
- data/lib/brakeman/checks/check_cross_site_scripting.rb +11 -9
- data/lib/brakeman/checks/check_evaluation.rb +1 -1
- data/lib/brakeman/checks/check_execute.rb +3 -3
- data/lib/brakeman/checks/check_link_to.rb +15 -13
- data/lib/brakeman/checks/check_link_to_href.rb +1 -1
- data/lib/brakeman/checks/check_mail_to.rb +1 -1
- data/lib/brakeman/checks/check_mass_assignment.rb +27 -13
- data/lib/brakeman/checks/check_redirect.rb +4 -4
- data/lib/brakeman/checks/check_select_tag.rb +1 -1
- data/lib/brakeman/checks/check_select_vulnerability.rb +1 -1
- data/lib/brakeman/checks/check_send.rb +2 -2
- data/lib/brakeman/checks/check_session_settings.rb +12 -5
- data/lib/brakeman/checks/check_single_quotes.rb +3 -3
- data/lib/brakeman/checks/check_skip_before_filter.rb +4 -3
- data/lib/brakeman/checks/check_sql.rb +30 -30
- data/lib/brakeman/checks/check_translate_bug.rb +11 -10
- data/lib/brakeman/checks/check_validation_regex.rb +36 -11
- data/lib/brakeman/checks/check_without_protection.rb +1 -1
- data/lib/brakeman/options.rb +6 -2
- data/lib/brakeman/processor.rb +6 -5
- data/lib/brakeman/processors/alias_processor.rb +153 -38
- data/lib/brakeman/processors/base_processor.rb +16 -21
- data/lib/brakeman/processors/controller_alias_processor.rb +24 -11
- data/lib/brakeman/processors/controller_processor.rb +25 -25
- data/lib/brakeman/processors/erb_template_processor.rb +6 -7
- data/lib/brakeman/processors/erubis_template_processor.rb +2 -3
- data/lib/brakeman/processors/gem_processor.rb +5 -4
- data/lib/brakeman/processors/haml_template_processor.rb +4 -6
- data/lib/brakeman/processors/lib/find_all_calls.rb +3 -3
- data/lib/brakeman/processors/lib/find_call.rb +2 -2
- data/lib/brakeman/processors/lib/find_return_value.rb +134 -0
- data/lib/brakeman/processors/lib/processor_helper.rb +24 -2
- data/lib/brakeman/processors/lib/rails2_config_processor.rb +13 -14
- data/lib/brakeman/processors/lib/rails2_route_processor.rb +9 -4
- data/lib/brakeman/processors/lib/rails3_config_processor.rb +8 -8
- data/lib/brakeman/processors/lib/rails3_route_processor.rb +23 -21
- data/lib/brakeman/processors/lib/render_helper.rb +2 -2
- data/lib/brakeman/processors/library_processor.rb +2 -2
- data/lib/brakeman/processors/model_processor.rb +16 -12
- data/lib/brakeman/processors/output_processor.rb +2 -1
- data/lib/brakeman/processors/template_alias_processor.rb +12 -8
- data/lib/brakeman/report.rb +28 -14
- data/lib/brakeman/rescanner.rb +5 -5
- data/lib/brakeman/scanner.rb +56 -94
- data/lib/brakeman/templates/header.html.erb +7 -2
- data/lib/brakeman/tracker.rb +14 -4
- data/lib/brakeman/util.rb +38 -17
- data/lib/brakeman/version.rb +1 -1
- data/lib/brakeman/warning.rb +14 -6
- data/lib/ruby_parser/bm_sexp.rb +157 -57
- data/lib/ruby_parser/bm_sexp_processor.rb +1 -2
- metadata +26 -25
- data/lib/ruby_parser/ruby18_parser.rb +0 -5544
- data/lib/ruby_parser/ruby19_parser.rb +0 -5756
- data/lib/ruby_parser/ruby_lexer.rb +0 -1349
- data/lib/ruby_parser/ruby_parser.rb +0 -5
- 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
|
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
|
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 =
|
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 =
|
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,
|
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
|
-
|
47
|
+
exp.body = process_all! exp.body
|
48
48
|
@model = nil
|
49
|
-
|
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
|
-
|
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
|
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(
|
80
|
+
@model[:includes] << class_name(first_arg) if @model
|
81
81
|
when :attr_accessible
|
82
82
|
@model[:attr_accessible] ||= []
|
83
|
-
args =
|
84
|
-
|
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 =
|
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
|
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
|
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 =
|
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
|
-
|
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
|
54
|
-
if
|
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,
|
60
|
+
env[Sexp.new(:lvar, arg)] = Sexp.new(:call, model, :new)
|
57
61
|
else
|
58
|
-
env[Sexp.new(:lvar,
|
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
|
65
|
-
env[Sexp.new(:lvar,
|
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
|
data/lib/brakeman/report.rb
CHANGED
@@ -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
|
-
|
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
|
-
:
|
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
|
data/lib/brakeman/rescanner.rb
CHANGED
@@ -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|
|
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
|
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
|
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
|
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
|
193
|
+
process_lib path if @app_tree.path_exists?(path)
|
194
194
|
|
195
195
|
lib = nil
|
196
196
|
|
data/lib/brakeman/scanner.rb
CHANGED
@@ -1,13 +1,7 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
begin
|
3
|
-
|
4
|
-
|
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
|
-
@
|
38
|
-
|
39
|
-
|
40
|
-
|
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
|
50
|
-
|
51
|
-
|
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
|
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
|
-
|
106
|
-
|
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
|
119
|
-
if
|
120
|
-
@processor.process_gems(parse_ruby(
|
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(
|
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
|
-
|
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(
|
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
|
-
|
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
|
-
|
155
|
+
@app_tree.lib_paths.each do |f|
|
169
156
|
Brakeman.debug "Processing #{f}"
|
170
|
-
|
171
|
-
|
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(
|
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
|
178
|
+
if @app_tree.exists?("config/routes.rb")
|
195
179
|
begin
|
196
|
-
@processor.process_routes parse_ruby(
|
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
|
-
|
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
|
-
|
198
|
+
@app_tree.controller_paths.each do |f|
|
218
199
|
Brakeman.debug "Processing #{f}"
|
219
|
-
|
220
|
-
|
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
|
-
|
235
|
-
|
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(
|
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
|
-
|
266
|
-
|
267
|
-
|
268
|
-
total = template_files.length
|
237
|
+
count = 0
|
238
|
+
total = @app_tree.template_paths.length
|
269
239
|
|
270
|
-
|
240
|
+
@app_tree.template_paths.each do |path|
|
271
241
|
Brakeman.debug "Processing #{path}"
|
272
|
-
|
273
|
-
|
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
|
-
|
288
|
-
|
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 =
|
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
|
-
|
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
|
-
|
319
|
+
@app_tree.model_paths.each do |f|
|
359
320
|
Brakeman.debug "Processing #{f}"
|
360
|
-
|
361
|
-
|
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(
|
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
|