brakeman 0.9.2 → 1.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/brakeman +20 -5
- data/lib/brakeman.rb +54 -14
- data/lib/brakeman/call_index.rb +204 -0
- data/lib/{checks.rb → brakeman/checks.rb} +27 -12
- data/lib/{checks → brakeman/checks}/base_check.rb +36 -15
- data/lib/{checks → brakeman/checks}/check_basic_auth.rb +3 -3
- data/lib/{checks → brakeman/checks}/check_cross_site_scripting.rb +22 -19
- data/lib/{checks → brakeman/checks}/check_default_routes.rb +7 -5
- data/lib/{checks → brakeman/checks}/check_escape_function.rb +3 -4
- data/lib/{checks → brakeman/checks}/check_evaluation.rb +8 -6
- data/lib/{checks → brakeman/checks}/check_execute.rb +14 -14
- data/lib/brakeman/checks/check_file_access.rb +52 -0
- data/lib/{checks → brakeman/checks}/check_filter_skipping.rb +3 -4
- data/lib/{checks → brakeman/checks}/check_forgery_setting.rb +3 -3
- data/lib/{checks → brakeman/checks}/check_mail_to.rb +7 -6
- data/lib/{checks → brakeman/checks}/check_mass_assignment.rb +27 -7
- data/lib/{checks → brakeman/checks}/check_model_attributes.rb +7 -7
- data/lib/{checks → brakeman/checks}/check_nested_attributes.rb +3 -4
- data/lib/{checks → brakeman/checks}/check_quote_table_name.rb +6 -5
- data/lib/{checks → brakeman/checks}/check_redirect.rb +31 -15
- data/lib/{checks → brakeman/checks}/check_render.rb +5 -3
- data/lib/{checks → brakeman/checks}/check_response_splitting.rb +3 -4
- data/lib/brakeman/checks/check_send_file.rb +17 -0
- data/lib/{checks → brakeman/checks}/check_session_settings.rb +16 -12
- data/lib/{checks → brakeman/checks}/check_sql.rb +29 -17
- data/lib/{checks → brakeman/checks}/check_strip_tags.rb +6 -5
- data/lib/{checks → brakeman/checks}/check_translate_bug.rb +7 -6
- data/lib/{checks → brakeman/checks}/check_validation_regex.rb +3 -3
- data/lib/{checks → brakeman/checks}/check_without_protection.rb +8 -8
- data/lib/brakeman/processor.rb +93 -0
- data/lib/{processors → brakeman/processors}/alias_processor.rb +9 -7
- data/lib/{processors → brakeman/processors}/base_processor.rb +5 -5
- data/lib/brakeman/processors/config_processor.rb +14 -0
- data/lib/{processors → brakeman/processors}/controller_alias_processor.rb +8 -8
- data/lib/{processors → brakeman/processors}/controller_processor.rb +6 -6
- data/lib/{processors → brakeman/processors}/erb_template_processor.rb +2 -2
- data/lib/{processors → brakeman/processors}/erubis_template_processor.rb +2 -3
- data/lib/{processors → brakeman/processors}/gem_processor.rb +3 -2
- data/lib/{processors → brakeman/processors}/haml_template_processor.rb +3 -3
- data/lib/brakeman/processors/lib/find_all_calls.rb +105 -0
- data/lib/{processors → brakeman/processors}/lib/find_call.rb +4 -4
- data/lib/{processors → brakeman/processors}/lib/processor_helper.rb +1 -1
- data/lib/{processors → brakeman/processors}/lib/rails2_config_processor.rb +10 -13
- data/lib/{processors → brakeman/processors}/lib/rails2_route_processor.rb +6 -5
- data/lib/{processors → brakeman/processors}/lib/rails3_config_processor.rb +7 -10
- data/lib/{processors → brakeman/processors}/lib/rails3_route_processor.rb +13 -5
- data/lib/{processors → brakeman/processors}/lib/render_helper.rb +12 -4
- data/lib/{processors → brakeman/processors}/lib/route_helper.rb +1 -1
- data/lib/{processors → brakeman/processors}/library_processor.rb +4 -4
- data/lib/{processors → brakeman/processors}/model_processor.rb +3 -3
- data/lib/{processors → brakeman/processors}/output_processor.rb +5 -6
- data/lib/{processors → brakeman/processors}/params_processor.rb +1 -2
- data/lib/brakeman/processors/route_processor.rb +17 -0
- data/lib/{processors → brakeman/processors}/template_alias_processor.rb +5 -5
- data/lib/{processors → brakeman/processors}/template_processor.rb +2 -2
- data/lib/{report.rb → brakeman/report.rb} +54 -48
- data/lib/{scanner.rb → brakeman/scanner.rb} +26 -17
- data/lib/{tracker.rb → brakeman/tracker.rb} +47 -38
- data/lib/{util.rb → brakeman/util.rb} +16 -1
- data/lib/brakeman/version.rb +3 -0
- data/lib/{warning.rb → brakeman/warning.rb} +9 -9
- metadata +81 -69
- data/lib/checks/check_file_access.rb +0 -48
- data/lib/checks/check_send_file.rb +0 -15
- data/lib/format/style.css +0 -105
- data/lib/processor.rb +0 -91
- data/lib/processors/config_processor.rb +0 -5
- data/lib/processors/lib/find_model_call.rb +0 -43
- data/lib/processors/route_processor.rb +0 -11
- data/lib/version.rb +0 -1
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'processors/base_processor'
|
1
|
+
require 'brakeman/processors/base_processor'
|
2
2
|
|
3
3
|
#Finds method calls matching the given target(s).
|
4
4
|
#
|
@@ -29,10 +29,10 @@ require 'processors/base_processor'
|
|
29
29
|
#
|
30
30
|
# #Find all calls to sub, sub!, gsub, or gsub!
|
31
31
|
# FindCall.new nil, /^g?sub!?$/
|
32
|
-
class FindCall < BaseProcessor
|
32
|
+
class Brakeman::FindCall < Brakeman::BaseProcessor
|
33
33
|
|
34
|
-
def initialize targets, methods, in_depth = false
|
35
|
-
super
|
34
|
+
def initialize targets, methods, tracker, in_depth = false
|
35
|
+
super tracker
|
36
36
|
@calls = []
|
37
37
|
@find_targets = targets
|
38
38
|
@find_methods = methods
|
@@ -1,12 +1,9 @@
|
|
1
|
-
require 'processors/base_processor'
|
2
|
-
require 'processors/alias_processor'
|
3
|
-
|
4
1
|
#Replace block variable in
|
5
2
|
#
|
6
3
|
# Rails::Initializer.run |config|
|
7
4
|
#
|
8
5
|
#with this value so we can keep track of it.
|
9
|
-
RAILS_CONFIG = Sexp.new(:const, :"!BRAKEMAN_RAILS_CONFIG")
|
6
|
+
Brakeman::RAILS_CONFIG = Sexp.new(:const, :"!BRAKEMAN_RAILS_CONFIG") unless defined? Brakeman::RAILS_CONFIG
|
10
7
|
|
11
8
|
#Processes configuration. Results are put in tracker.config.
|
12
9
|
#
|
@@ -22,7 +19,7 @@ RAILS_CONFIG = Sexp.new(:const, :"!BRAKEMAN_RAILS_CONFIG")
|
|
22
19
|
# tracker.config[:rails][:action_controller][:session_store]
|
23
20
|
#
|
24
21
|
#Values for tracker.config[:rails] will still be Sexps.
|
25
|
-
class
|
22
|
+
class Brakeman::Rails2ConfigProcessor < Brakeman::BaseProcessor
|
26
23
|
def initialize *args
|
27
24
|
super
|
28
25
|
@tracker.config[:rails] ||= {}
|
@@ -30,7 +27,7 @@ class ConfigProcessor < BaseProcessor
|
|
30
27
|
|
31
28
|
#Use this method to process configuration file
|
32
29
|
def process_config src
|
33
|
-
res = ConfigAliasProcessor.new.process_safely(src)
|
30
|
+
res = Brakeman::ConfigAliasProcessor.new.process_safely(src)
|
34
31
|
process res
|
35
32
|
end
|
36
33
|
|
@@ -49,7 +46,7 @@ class ConfigProcessor < BaseProcessor
|
|
49
46
|
|
50
47
|
#Look for configuration settings
|
51
48
|
def process_attrasgn exp
|
52
|
-
if exp[1] == RAILS_CONFIG
|
49
|
+
if exp[1] == Brakeman::RAILS_CONFIG
|
53
50
|
#Get rid of '=' at end
|
54
51
|
attribute = exp[2].to_s[0..-2].to_sym
|
55
52
|
if exp[3].length > 2
|
@@ -86,12 +83,12 @@ class ConfigProcessor < BaseProcessor
|
|
86
83
|
def include_rails_config? exp
|
87
84
|
target = exp[1]
|
88
85
|
if call? target
|
89
|
-
if target[1] == RAILS_CONFIG
|
86
|
+
if target[1] == Brakeman::RAILS_CONFIG
|
90
87
|
true
|
91
88
|
else
|
92
89
|
include_rails_config? target
|
93
90
|
end
|
94
|
-
elsif target == RAILS_CONFIG
|
91
|
+
elsif target == Brakeman::RAILS_CONFIG
|
95
92
|
true
|
96
93
|
else
|
97
94
|
false
|
@@ -110,7 +107,7 @@ class ConfigProcessor < BaseProcessor
|
|
110
107
|
attribute = exp[2].to_s[0..-2].to_sym
|
111
108
|
get_rails_config(exp[1]) << attribute
|
112
109
|
elsif call? exp
|
113
|
-
if exp[1] == RAILS_CONFIG
|
110
|
+
if exp[1] == Brakeman::RAILS_CONFIG
|
114
111
|
[exp[2]]
|
115
112
|
else
|
116
113
|
get_rails_config(exp[1]) << exp[2]
|
@@ -122,7 +119,7 @@ class ConfigProcessor < BaseProcessor
|
|
122
119
|
end
|
123
120
|
|
124
121
|
#This is necessary to replace block variable so we can track config settings
|
125
|
-
class ConfigAliasProcessor < AliasProcessor
|
122
|
+
class Brakeman::ConfigAliasProcessor < Brakeman::AliasProcessor
|
126
123
|
|
127
124
|
RAILS_INIT = Sexp.new(:colon2, Sexp.new(:const, :Rails), :Initializer)
|
128
125
|
|
@@ -132,13 +129,13 @@ class ConfigAliasProcessor < AliasProcessor
|
|
132
129
|
# ...
|
133
130
|
# end
|
134
131
|
#
|
135
|
-
#and replace config with RAILS_CONFIG
|
132
|
+
#and replace config with Brakeman::RAILS_CONFIG
|
136
133
|
def process_iter exp
|
137
134
|
target = exp[1][1]
|
138
135
|
method = exp[1][2]
|
139
136
|
|
140
137
|
if sexp? target and target == RAILS_INIT and method == :run
|
141
|
-
exp[2][2] = RAILS_CONFIG
|
138
|
+
exp[2][2] = Brakeman::RAILS_CONFIG
|
142
139
|
end
|
143
140
|
|
144
141
|
process_default exp
|
@@ -1,10 +1,11 @@
|
|
1
|
-
require 'processors/base_processor'
|
1
|
+
require 'brakeman/processors/base_processor'
|
2
|
+
|
2
3
|
#Processes the Sexp from routes.rb. Stores results in tracker.routes.
|
3
4
|
#
|
4
5
|
#Note that it is only interested in determining what methods on which
|
5
6
|
#controllers are used as routes, not the generated URLs for routes.
|
6
|
-
class
|
7
|
-
include RouteHelper
|
7
|
+
class Brakeman::Rails2RoutesProcessor < Brakeman::BaseProcessor
|
8
|
+
include Brakeman::RouteHelper
|
8
9
|
|
9
10
|
attr_reader :map, :nested, :current_controller
|
10
11
|
|
@@ -22,7 +23,7 @@ class RoutesProcessor < BaseProcessor
|
|
22
23
|
#This method first calls RouteAliasProcessor#process_safely on the +exp+,
|
23
24
|
#so it does not modify the +exp+.
|
24
25
|
def process_routes exp
|
25
|
-
process RouteAliasProcessor.new.process_safely(exp)
|
26
|
+
process Brakeman::RouteAliasProcessor.new.process_safely(exp)
|
26
27
|
end
|
27
28
|
|
28
29
|
#Looking for mapping of routes
|
@@ -273,7 +274,7 @@ end
|
|
273
274
|
|
274
275
|
#This is for a really specific case where a hash is used as arguments
|
275
276
|
#to one of the map methods.
|
276
|
-
class RouteAliasProcessor < AliasProcessor
|
277
|
+
class Brakeman::RouteAliasProcessor < Brakeman::AliasProcessor
|
277
278
|
|
278
279
|
#This replaces
|
279
280
|
# { :some => :hash }.keys
|
@@ -1,7 +1,4 @@
|
|
1
|
-
|
2
|
-
require 'processors/alias_processor'
|
3
|
-
|
4
|
-
RAILS_CONFIG = Sexp.new(:call, nil, :config, Sexp.new(:arglist))
|
1
|
+
Brakeman::RAILS_CONFIG = Sexp.new(:call, nil, :config, Sexp.new(:arglist))
|
5
2
|
|
6
3
|
#Processes configuration. Results are put in tracker.config.
|
7
4
|
#
|
@@ -17,7 +14,7 @@ RAILS_CONFIG = Sexp.new(:call, nil, :config, Sexp.new(:arglist))
|
|
17
14
|
# tracker.config[:rails][:active_record][:whitelist_attributes]
|
18
15
|
#
|
19
16
|
#Values for tracker.config[:rails] will still be Sexps.
|
20
|
-
class
|
17
|
+
class Brakeman::Rails3ConfigProcessor < Brakeman::BaseProcessor
|
21
18
|
def initialize *args
|
22
19
|
super
|
23
20
|
@tracker.config[:rails] ||= {}
|
@@ -26,7 +23,7 @@ class ConfigProcessor < BaseProcessor
|
|
26
23
|
|
27
24
|
#Use this method to process configuration file
|
28
25
|
def process_config src
|
29
|
-
res = AliasProcessor.new.process_safely(src)
|
26
|
+
res = Brakeman::AliasProcessor.new.process_safely(src)
|
30
27
|
process res
|
31
28
|
end
|
32
29
|
|
@@ -56,7 +53,7 @@ class ConfigProcessor < BaseProcessor
|
|
56
53
|
def process_attrasgn exp
|
57
54
|
return exp unless @inside_config
|
58
55
|
|
59
|
-
if exp[1] == RAILS_CONFIG
|
56
|
+
if exp[1] == Brakeman::RAILS_CONFIG
|
60
57
|
#Get rid of '=' at end
|
61
58
|
attribute = exp[2].to_s[0..-2].to_sym
|
62
59
|
if exp[3].length > 2
|
@@ -83,12 +80,12 @@ class ConfigProcessor < BaseProcessor
|
|
83
80
|
def include_rails_config? exp
|
84
81
|
target = exp[1]
|
85
82
|
if call? target
|
86
|
-
if target[1] == RAILS_CONFIG
|
83
|
+
if target[1] == Brakeman::RAILS_CONFIG
|
87
84
|
true
|
88
85
|
else
|
89
86
|
include_rails_config? target
|
90
87
|
end
|
91
|
-
elsif target == RAILS_CONFIG
|
88
|
+
elsif target == Brakeman::RAILS_CONFIG
|
92
89
|
true
|
93
90
|
else
|
94
91
|
false
|
@@ -107,7 +104,7 @@ class ConfigProcessor < BaseProcessor
|
|
107
104
|
attribute = exp[2].to_s[0..-2].to_sym
|
108
105
|
get_rails_config(exp[1]) << attribute
|
109
106
|
elsif call? exp
|
110
|
-
if exp[1] == RAILS_CONFIG
|
107
|
+
if exp[1] == Brakeman::RAILS_CONFIG
|
111
108
|
[exp[2]]
|
112
109
|
else
|
113
110
|
get_rails_config(exp[1]) << exp[2]
|
@@ -2,8 +2,8 @@
|
|
2
2
|
#
|
3
3
|
#Note that it is only interested in determining what methods on which
|
4
4
|
#controllers are used as routes, not the generated URLs for routes.
|
5
|
-
class
|
6
|
-
include RouteHelper
|
5
|
+
class Brakeman::Rails3RoutesProcessor < Brakeman::BaseProcessor
|
6
|
+
include Brakeman::RouteHelper
|
7
7
|
|
8
8
|
attr_reader :map, :nested, :current_controller
|
9
9
|
|
@@ -126,7 +126,7 @@ class RoutesProcessor < BaseProcessor
|
|
126
126
|
def process_verb exp
|
127
127
|
args = exp[3][1..-1]
|
128
128
|
|
129
|
-
if symbol? args[0]
|
129
|
+
if symbol? args[0] and not hash? args[1]
|
130
130
|
@tracker.routes[@current_controller] << args[0][1]
|
131
131
|
elsif hash? args[1]
|
132
132
|
hash_iterate args[1] do |k, v|
|
@@ -162,7 +162,9 @@ class RoutesProcessor < BaseProcessor
|
|
162
162
|
|
163
163
|
def process_resources exp
|
164
164
|
if exp[3] and exp[3][2] and exp[3][2][0] == :hash
|
165
|
+
self.current_controller = exp[3][1][1]
|
165
166
|
#handle hash
|
167
|
+
add_resources_routes
|
166
168
|
elsif exp[3][1..-1].all? { |s| symbol? s }
|
167
169
|
exp[3][1..-1].each do |s|
|
168
170
|
self.current_controller = s[1]
|
@@ -174,9 +176,15 @@ class RoutesProcessor < BaseProcessor
|
|
174
176
|
end
|
175
177
|
|
176
178
|
def process_resource exp
|
179
|
+
#Does resource even take more than one controller name?
|
177
180
|
exp[3][1..-1].each do |s|
|
178
|
-
|
179
|
-
|
181
|
+
if symbol? s
|
182
|
+
self.current_controller = pluralize(s[1].to_s)
|
183
|
+
add_resource_routes
|
184
|
+
else
|
185
|
+
#handle something else, like options
|
186
|
+
#or something?
|
187
|
+
end
|
180
188
|
end
|
181
189
|
|
182
190
|
exp
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'digest/sha1'
|
2
2
|
|
3
3
|
#Processes a call to render() in a controller or template
|
4
|
-
module RenderHelper
|
4
|
+
module Brakeman::RenderHelper
|
5
5
|
|
6
6
|
#Process s(:render, TYPE, OPTIONS)
|
7
7
|
def process_render exp
|
@@ -50,7 +50,7 @@ module RenderHelper
|
|
50
50
|
name = name.to_s.gsub(/^\//, "")
|
51
51
|
template = @tracker.templates[name.to_sym]
|
52
52
|
unless template
|
53
|
-
warn "[Notice] No such template: #{name}" if
|
53
|
+
warn "[Notice] No such template: #{name}" if @tracker.options[:debug]
|
54
54
|
return
|
55
55
|
end
|
56
56
|
|
@@ -99,13 +99,21 @@ module RenderHelper
|
|
99
99
|
end
|
100
100
|
end
|
101
101
|
|
102
|
-
template_env[Sexp.new(:call, nil, variable, Sexp.new(:arglist))] = Sexp.new(:call, Sexp.new(:const, Tracker::UNKNOWN_MODEL), :new, Sexp.new(:arglist))
|
102
|
+
template_env[Sexp.new(:call, nil, variable, Sexp.new(:arglist))] = Sexp.new(:call, Sexp.new(:const, Brakeman::Tracker::UNKNOWN_MODEL), :new, Sexp.new(:arglist))
|
103
|
+
end
|
104
|
+
|
105
|
+
#Set original_line for values so it is clear
|
106
|
+
#that values came from another file
|
107
|
+
template_env.all.each do |var, value|
|
108
|
+
unless value.original_line
|
109
|
+
value.original_line = value.line
|
110
|
+
end
|
103
111
|
end
|
104
112
|
|
105
113
|
#Run source through AliasProcessor with instance variables from the
|
106
114
|
#current environment.
|
107
115
|
#TODO: Add in :locals => { ... } to environment
|
108
|
-
src = TemplateAliasProcessor.new(@tracker, template).process_safely(template[:src], template_env)
|
116
|
+
src = Brakeman::TemplateAliasProcessor.new(@tracker, template).process_safely(template[:src], template_env)
|
109
117
|
|
110
118
|
#Run alias-processed src through the template processor to pull out
|
111
119
|
#information and outputs.
|
@@ -1,13 +1,13 @@
|
|
1
|
-
require 'processors/base_processor'
|
2
|
-
require 'processors/alias_processor'
|
1
|
+
require 'brakeman/processors/base_processor'
|
2
|
+
require 'brakeman/processors/alias_processor'
|
3
3
|
|
4
4
|
#Process generic library and stores it in Tracker.libs
|
5
|
-
class LibraryProcessor < BaseProcessor
|
5
|
+
class Brakeman::LibraryProcessor < Brakeman::BaseProcessor
|
6
6
|
|
7
7
|
def initialize tracker
|
8
8
|
super
|
9
9
|
@file_name = nil
|
10
|
-
@alias_processor = AliasProcessor.new
|
10
|
+
@alias_processor = Brakeman::AliasProcessor.new
|
11
11
|
end
|
12
12
|
|
13
13
|
def process_library src, file_name = nil
|
@@ -1,7 +1,7 @@
|
|
1
|
-
require 'processors/base_processor'
|
1
|
+
require 'brakeman/processors/base_processor'
|
2
2
|
|
3
3
|
#Processes models. Puts results in tracker.models
|
4
|
-
class ModelProcessor < BaseProcessor
|
4
|
+
class Brakeman::ModelProcessor < Brakeman::BaseProcessor
|
5
5
|
def initialize tracker
|
6
6
|
super
|
7
7
|
@model = nil
|
@@ -19,7 +19,7 @@ class ModelProcessor < BaseProcessor
|
|
19
19
|
#s(:class, NAME, PARENT, s(:scope ...))
|
20
20
|
def process_class exp
|
21
21
|
if @model
|
22
|
-
warn "[Notice] Skipping inner class: #{class_name exp[1]}" if
|
22
|
+
warn "[Notice] Skipping inner class: #{class_name exp[1]}" if @tracker.options[:debug]
|
23
23
|
ignore
|
24
24
|
else
|
25
25
|
@model = { :name => class_name(exp[1]),
|
@@ -1,13 +1,12 @@
|
|
1
|
-
require 'rubygems'
|
2
1
|
require 'ruby2ruby'
|
3
|
-
require 'util'
|
2
|
+
require 'brakeman/util'
|
4
3
|
|
5
4
|
#Produces formatted output strings from Sexps.
|
6
5
|
#Recommended usage is
|
7
6
|
#
|
8
7
|
# OutputProcessor.new.format(Sexp.new(:str, "hello"))
|
9
|
-
class OutputProcessor < Ruby2Ruby
|
10
|
-
include Util
|
8
|
+
class Brakeman::OutputProcessor < Ruby2Ruby
|
9
|
+
include Brakeman::Util
|
11
10
|
|
12
11
|
#Copies +exp+ and then formats it.
|
13
12
|
def format exp
|
@@ -20,7 +19,7 @@ class OutputProcessor < Ruby2Ruby
|
|
20
19
|
begin
|
21
20
|
super exp if sexp? exp and not exp.empty?
|
22
21
|
rescue Exception => e
|
23
|
-
warn "While formatting #{exp}: #{e}\n#{e.backtrace.join("\n")}" if
|
22
|
+
warn "While formatting #{exp}: #{e}\n#{e.backtrace.join("\n")}" if @tracker.options[:debug]
|
24
23
|
end
|
25
24
|
end
|
26
25
|
|
@@ -203,7 +202,7 @@ class OutputProcessor < Ruby2Ruby
|
|
203
202
|
end
|
204
203
|
|
205
204
|
def process_const exp
|
206
|
-
if exp[0] == Tracker::UNKNOWN_MODEL
|
205
|
+
if exp[0] == Brakeman::Tracker::UNKNOWN_MODEL
|
207
206
|
exp.clear
|
208
207
|
"(Unresolved Model)"
|
209
208
|
else
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'brakeman/processors/base_processor'
|
2
|
+
require 'brakeman/processors/alias_processor'
|
3
|
+
require 'brakeman/processors/lib/route_helper'
|
4
|
+
require 'brakeman/util'
|
5
|
+
require 'brakeman/processors/lib/rails3_route_processor.rb'
|
6
|
+
require 'brakeman/processors/lib/rails2_route_processor.rb'
|
7
|
+
require 'set'
|
8
|
+
|
9
|
+
class Brakeman::RoutesProcessor
|
10
|
+
def self.new tracker
|
11
|
+
if tracker.options[:rails3]
|
12
|
+
Brakeman::Rails3RoutesProcessor.new tracker
|
13
|
+
else
|
14
|
+
Brakeman::Rails2RoutesProcessor.new tracker
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
require 'set'
|
2
|
-
require 'processors/alias_processor'
|
3
|
-
require 'processors/lib/render_helper'
|
2
|
+
require 'brakeman/processors/alias_processor'
|
3
|
+
require 'brakeman/processors/lib/render_helper'
|
4
4
|
|
5
5
|
#Processes aliasing in templates.
|
6
6
|
#Handles calls to +render+.
|
7
|
-
class TemplateAliasProcessor < AliasProcessor
|
8
|
-
include RenderHelper
|
7
|
+
class Brakeman::TemplateAliasProcessor < Brakeman::AliasProcessor
|
8
|
+
include Brakeman::RenderHelper
|
9
9
|
|
10
10
|
FORM_METHODS = Set.new([:form_for, :remote_form_for, :form_remote_for])
|
11
11
|
|
@@ -44,7 +44,7 @@ class TemplateAliasProcessor < AliasProcessor
|
|
44
44
|
if model == target[1]
|
45
45
|
env[Sexp.new(:lvar, args[1])] = Sexp.new(:call, model, :new, Sexp.new(:arglist))
|
46
46
|
else
|
47
|
-
env[Sexp.new(:lvar, args[1])] = Sexp.new(:call, Sexp.new(:const, Tracker::UNKNOWN_MODEL), :new, Sexp.new(:arglist))
|
47
|
+
env[Sexp.new(:lvar, args[1])] = Sexp.new(:call, Sexp.new(:const, Brakeman::Tracker::UNKNOWN_MODEL), :new, Sexp.new(:arglist))
|
48
48
|
end
|
49
49
|
|
50
50
|
process block if sexp? block
|
@@ -1,7 +1,7 @@
|
|
1
|
-
require 'processors/base_processor'
|
1
|
+
require 'brakeman/processors/base_processor'
|
2
2
|
|
3
3
|
#Base Processor for templates/views
|
4
|
-
class TemplateProcessor < BaseProcessor
|
4
|
+
class Brakeman::TemplateProcessor < Brakeman::BaseProcessor
|
5
5
|
|
6
6
|
#Initializes template information.
|
7
7
|
def initialize tracker, template_name, called_from = nil, file_name = nil
|
@@ -1,9 +1,8 @@
|
|
1
|
-
require 'rubygems'
|
2
1
|
require 'cgi'
|
3
2
|
require 'set'
|
4
3
|
require 'ruport'
|
5
|
-
require 'processors/output_processor'
|
6
|
-
require 'util'
|
4
|
+
require 'brakeman/processors/output_processor'
|
5
|
+
require 'brakeman/util'
|
7
6
|
|
8
7
|
#Fix for Ruport under 1.9
|
9
8
|
#as reported here: https://github.com/ruport/ruport/pull/7
|
@@ -19,8 +18,8 @@ end
|
|
19
18
|
#Generates a report based on the Tracker and the results of
|
20
19
|
#Tracker#run_checks. Be sure to +run_checks+ before generating
|
21
20
|
#a report.
|
22
|
-
class Report
|
23
|
-
include Util
|
21
|
+
class Brakeman::Report
|
22
|
+
include Brakeman::Util
|
24
23
|
|
25
24
|
attr_reader :tracker, :checks
|
26
25
|
|
@@ -47,10 +46,10 @@ class Report
|
|
47
46
|
#Add number of high confidence warnings in summary.
|
48
47
|
#Skipping for CSV because it makes the cell text instead of
|
49
48
|
#a number.
|
50
|
-
unless
|
49
|
+
unless tracker.options[:output_format] == :to_csv
|
51
50
|
summary = warnings_summary
|
52
51
|
|
53
|
-
if
|
52
|
+
if tracker.options[:output_format] == :to_html
|
54
53
|
warnings = "#{warnings} <span class='high-confidence'>(#{summary[:high_confidence]})</span>"
|
55
54
|
else
|
56
55
|
warnings = "#{warnings} (#{summary[:high_confidence]})"
|
@@ -84,9 +83,9 @@ class Report
|
|
84
83
|
|
85
84
|
|
86
85
|
tracker.errors.each do |w|
|
87
|
-
p w if
|
86
|
+
p w if tracker.options[:debug]
|
88
87
|
|
89
|
-
if
|
88
|
+
if tracker.options[:output_format] == :to_html
|
90
89
|
w[:error] = CGI.escapeHTML w[:error]
|
91
90
|
end
|
92
91
|
|
@@ -103,10 +102,10 @@ class Report
|
|
103
102
|
def generate_warnings
|
104
103
|
table = Ruport::Data::Table(["Confidence", "Class", "Method", "Warning Type", "Message"])
|
105
104
|
checks.warnings.each do |warning|
|
106
|
-
next if warning.confidence >
|
105
|
+
next if warning.confidence > tracker.options[:min_confidence]
|
107
106
|
w = warning.to_row
|
108
107
|
|
109
|
-
if
|
108
|
+
if tracker.options[:output_format] == :to_html
|
110
109
|
w["Confidence"] = HTML_CONFIDENCE[w["Confidence"]]
|
111
110
|
w["Message"] = with_context warning, w["Message"]
|
112
111
|
else
|
@@ -133,10 +132,10 @@ class Report
|
|
133
132
|
unless checks.template_warnings.empty?
|
134
133
|
table = Ruport::Data::Table(["Confidence", "Template", "Warning Type", "Message"])
|
135
134
|
checks.template_warnings.each do |warning|
|
136
|
-
next if warning.confidence >
|
135
|
+
next if warning.confidence > tracker.options[:min_confidence]
|
137
136
|
w = warning.to_row :template
|
138
137
|
|
139
|
-
if
|
138
|
+
if tracker.options[:output_format] == :to_html
|
140
139
|
w["Confidence"] = HTML_CONFIDENCE[w["Confidence"]]
|
141
140
|
w["Message"] = with_context warning, w["Message"]
|
142
141
|
else
|
@@ -164,10 +163,10 @@ class Report
|
|
164
163
|
unless checks.model_warnings.empty?
|
165
164
|
table = Ruport::Data::Table(["Confidence", "Model", "Warning Type", "Message"])
|
166
165
|
checks.model_warnings.each do |warning|
|
167
|
-
next if warning.confidence >
|
166
|
+
next if warning.confidence > tracker.options[:min_confidence]
|
168
167
|
w = warning.to_row :model
|
169
168
|
|
170
|
-
if
|
169
|
+
if tracker.options[:output_format] == :to_html
|
171
170
|
w["Confidence"] = HTML_CONFIDENCE[w["Confidence"]]
|
172
171
|
w["Message"] = with_context warning, w["Message"]
|
173
172
|
else
|
@@ -195,10 +194,10 @@ class Report
|
|
195
194
|
unless checks.controller_warnings.empty?
|
196
195
|
table = Ruport::Data::Table(["Confidence", "Controller", "Warning Type", "Message"])
|
197
196
|
checks.controller_warnings.each do |warning|
|
198
|
-
next if warning.confidence >
|
197
|
+
next if warning.confidence > tracker.options[:min_confidence]
|
199
198
|
w = warning.to_row :controller
|
200
199
|
|
201
|
-
if
|
200
|
+
if tracker.options[:output_format] == :to_html
|
202
201
|
w["Confidence"] = HTML_CONFIDENCE[w["Confidence"]]
|
203
202
|
w["Message"] = with_context warning, w["Message"]
|
204
203
|
else
|
@@ -259,13 +258,13 @@ class Report
|
|
259
258
|
|
260
259
|
#Generate listings of templates and their output
|
261
260
|
def generate_templates
|
262
|
-
out_processor = OutputProcessor.new
|
261
|
+
out_processor = Brakeman::OutputProcessor.new
|
263
262
|
table = Ruport::Data::Table(["Name", "Output"])
|
264
263
|
tracker.templates.each do |name, template|
|
265
264
|
unless template[:outputs].empty?
|
266
265
|
template[:outputs].each do |out|
|
267
266
|
out = out_processor.format out
|
268
|
-
out = CGI.escapeHTML(out) if
|
267
|
+
out = CGI.escapeHTML(out) if tracker.options[:output_format] == :to_html
|
269
268
|
table << { "Name" => name,
|
270
269
|
"Output" => out.gsub("\n", ";").gsub(/\s+/, " ") }
|
271
270
|
end
|
@@ -281,12 +280,12 @@ class Report
|
|
281
280
|
generate_overview.to_html << "<br/>" <<
|
282
281
|
generate_warning_overview.to_html
|
283
282
|
|
284
|
-
if
|
283
|
+
if tracker.options[:report_routes] or tracker.options[:debug]
|
285
284
|
out << "<h2>Controllers</h2>" <<
|
286
285
|
generate_controllers.to_html
|
287
286
|
end
|
288
287
|
|
289
|
-
if
|
288
|
+
if tracker.options[:debug]
|
290
289
|
out << "<h2>Templates</h2>" <<
|
291
290
|
generate_templates.to_html
|
292
291
|
end
|
@@ -318,12 +317,12 @@ class Report
|
|
318
317
|
generate_overview.to_s << "\n" <<
|
319
318
|
generate_warning_overview.to_s << "\n"
|
320
319
|
|
321
|
-
if
|
320
|
+
if tracker.options[:report_routes] or tracker.options[:debug]
|
322
321
|
out << "+CONTROLLERS+\n" <<
|
323
322
|
generate_controllers.to_s << "\n"
|
324
323
|
end
|
325
324
|
|
326
|
-
if
|
325
|
+
if tracker.options[:debug]
|
327
326
|
out << "+TEMPLATES+\n\n" <<
|
328
327
|
generate_templates.to_s << "\n"
|
329
328
|
end
|
@@ -353,12 +352,12 @@ class Report
|
|
353
352
|
generate_overview.to_csv << "\n" <<
|
354
353
|
generate_warning_overview.to_csv << "\n"
|
355
354
|
|
356
|
-
if
|
355
|
+
if tracker.options[:report_routes] or tracker.options[:debug]
|
357
356
|
out << "CONTROLLERS\n" <<
|
358
357
|
generate_controllers.to_csv << "\n"
|
359
358
|
end
|
360
359
|
|
361
|
-
if
|
360
|
+
if tracker.options[:debug]
|
362
361
|
out << "TEMPLATES\n\n" <<
|
363
362
|
generate_templates.to_csv << "\n"
|
364
363
|
end
|
@@ -389,19 +388,19 @@ class Report
|
|
389
388
|
def rails_version
|
390
389
|
if version = tracker.config[:rails_version]
|
391
390
|
return version
|
392
|
-
elsif
|
391
|
+
elsif tracker.options[:rails3]
|
393
392
|
return "3.x"
|
394
393
|
else
|
395
394
|
return "Unknown"
|
396
395
|
end
|
397
396
|
end
|
398
397
|
|
399
|
-
#Return header for HTML output. Uses CSS from
|
398
|
+
#Return header for HTML output. Uses CSS from tracker.options[:html_style]
|
400
399
|
def html_header
|
401
|
-
if File.exist?
|
402
|
-
css = File.read
|
400
|
+
if File.exist? tracker.options[:html_style]
|
401
|
+
css = File.read tracker.options[:html_style]
|
403
402
|
else
|
404
|
-
raise "Cannot find CSS stylesheet for HTML: #{
|
403
|
+
raise "Cannot find CSS stylesheet for HTML: #{tracker.options[:html_style]}"
|
405
404
|
end
|
406
405
|
|
407
406
|
<<-HTML
|
@@ -410,11 +409,15 @@ class Report
|
|
410
409
|
<head>
|
411
410
|
<title>Brakeman Report</title>
|
412
411
|
<script type="text/javascript">
|
413
|
-
function toggle(context){
|
414
|
-
|
415
|
-
|
412
|
+
function toggle(context) {
|
413
|
+
var elem = document.getElementById(context);
|
414
|
+
|
415
|
+
if (elem.style.display != "block")
|
416
|
+
elem.style.display = "block";
|
416
417
|
else
|
417
|
-
|
418
|
+
elem.style.display = "none";
|
419
|
+
|
420
|
+
elem.parentNode.scrollIntoView();
|
418
421
|
}
|
419
422
|
</script>
|
420
423
|
<style type="text/css">
|
@@ -431,7 +434,7 @@ class Report
|
|
431
434
|
<th>Checks Performed</th>
|
432
435
|
</tr>
|
433
436
|
<tr>
|
434
|
-
<td>#{File.expand_path
|
437
|
+
<td>#{File.expand_path tracker.options[:app_path]}</td>
|
435
438
|
<td>#{rails_version}</td>
|
436
439
|
<td>#{Time.now}</td>
|
437
440
|
<td>#{checks.checks_run.sort.join(", ")}</td>
|
@@ -442,13 +445,13 @@ class Report
|
|
442
445
|
|
443
446
|
#Generate header for text output
|
444
447
|
def text_header
|
445
|
-
"\n+BRAKEMAN REPORT+\n\nApplication path: #{File.expand_path
|
448
|
+
"\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"
|
446
449
|
end
|
447
450
|
|
448
451
|
#Generate header for CSV output
|
449
452
|
def csv_header
|
450
453
|
header = Ruport::Data::Table(["Application Path", "Report Generation Time", "Checks Performed", "Rails Version"])
|
451
|
-
header << [File.expand_path(
|
454
|
+
header << [File.expand_path(tracker.options[:app_path]), Time.now.to_s, checks.checks_run.sort.join(", "), rails_version]
|
452
455
|
"BRAKEMAN REPORT\n\n" << header.to_csv
|
453
456
|
end
|
454
457
|
|
@@ -465,10 +468,13 @@ class Report
|
|
465
468
|
checks.template_warnings].each do |warnings|
|
466
469
|
|
467
470
|
warnings.each do |warning|
|
468
|
-
|
471
|
+
unless warning.confidence > tracker.options[:min_confidence]
|
472
|
+
|
473
|
+
summary[warning.warning_type.to_s] += 1
|
469
474
|
|
470
|
-
|
471
|
-
|
475
|
+
if warning.confidence == 0
|
476
|
+
high_confidence_warnings += 1
|
477
|
+
end
|
472
478
|
end
|
473
479
|
end
|
474
480
|
end
|
@@ -480,7 +486,7 @@ class Report
|
|
480
486
|
#Return file name related to given warning. Uses +warning.file+ if it exists
|
481
487
|
def file_for warning
|
482
488
|
if warning.file
|
483
|
-
File.expand_path warning.file,
|
489
|
+
File.expand_path warning.file, tracker.options[:app_path]
|
484
490
|
else
|
485
491
|
case warning.warning_set
|
486
492
|
when :controller
|
@@ -518,7 +524,7 @@ class Report
|
|
518
524
|
end
|
519
525
|
end
|
520
526
|
|
521
|
-
path =
|
527
|
+
path = tracker.options[:app_path]
|
522
528
|
|
523
529
|
case type
|
524
530
|
when :controller
|
@@ -584,15 +590,15 @@ class Report
|
|
584
590
|
context = context_for warning
|
585
591
|
full_message = nil
|
586
592
|
|
587
|
-
if
|
588
|
-
|
589
|
-
message.length >
|
593
|
+
if tracker.options[:message_limit] and
|
594
|
+
tracker.options[:message_limit] > 0 and
|
595
|
+
message.length > tracker.options[:message_limit]
|
590
596
|
|
591
597
|
full_message = message
|
592
|
-
message = message[0..
|
598
|
+
message = message[0..tracker.options[:message_limit]] << "..."
|
593
599
|
end
|
594
600
|
|
595
|
-
if context.empty?
|
601
|
+
if context.empty? and not full_message
|
596
602
|
return CGI.escapeHTML(message)
|
597
603
|
end
|
598
604
|
|
@@ -665,7 +671,7 @@ class Report
|
|
665
671
|
[:model_warnings, "Model"], [:template_warnings, "Template"]].map do |meth, category|
|
666
672
|
|
667
673
|
checks.send(meth).map do |w|
|
668
|
-
next if w.confidence >
|
674
|
+
next if w.confidence > tracker.options[:min_confidence]
|
669
675
|
line = w.line || 0
|
670
676
|
w.warning_type.gsub!(/[^\w\s]/, ' ')
|
671
677
|
"#{file_for w}\t#{line}\t#{w.warning_type}\t#{category}\t#{w.format_message}\t#{TEXT_CONFIDENCE[w.confidence]}"
|