brakeman 2.5.0 → 2.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/CHANGES +14 -0
- data/README.md +6 -28
- data/lib/brakeman/checks/base_check.rb +5 -4
- data/lib/brakeman/checks/check_basic_auth.rb +1 -2
- data/lib/brakeman/checks/check_default_routes.rb +65 -15
- data/lib/brakeman/checks/check_detailed_exceptions.rb +5 -4
- data/lib/brakeman/checks/check_filter_skipping.rb +1 -1
- data/lib/brakeman/checks/check_forgery_setting.rb +9 -9
- data/lib/brakeman/checks/check_model_attr_accessible.rb +1 -1
- data/lib/brakeman/checks/check_model_attributes.rb +3 -3
- data/lib/brakeman/checks/check_model_serialize.rb +1 -1
- data/lib/brakeman/checks/check_redirect.rb +27 -6
- data/lib/brakeman/checks/check_render.rb +2 -2
- data/lib/brakeman/checks/check_skip_before_filter.rb +2 -2
- data/lib/brakeman/checks/check_sql.rb +2 -1
- data/lib/brakeman/file_parser.rb +49 -0
- data/lib/brakeman/options.rb +1 -1
- data/lib/brakeman/parsers/template_parser.rb +88 -0
- data/lib/brakeman/processors/alias_processor.rb +25 -2
- data/lib/brakeman/processors/controller_alias_processor.rb +3 -3
- data/lib/brakeman/processors/controller_processor.rb +106 -54
- data/lib/brakeman/processors/lib/rails3_route_processor.rb +27 -12
- data/lib/brakeman/processors/lib/route_helper.rb +1 -1
- data/lib/brakeman/processors/library_processor.rb +37 -28
- data/lib/brakeman/processors/model_processor.rb +117 -34
- data/lib/brakeman/report/report_base.rb +1 -1
- data/lib/brakeman/rescanner.rb +84 -35
- data/lib/brakeman/scanner.rb +84 -148
- data/lib/brakeman/tracker.rb +32 -12
- data/lib/brakeman/util.rb +13 -4
- data/lib/brakeman/version.rb +1 -1
- data/lib/brakeman/warning_codes.rb +2 -1
- metadata +6 -4
- metadata.gz.sig +0 -0
@@ -89,18 +89,17 @@ class Brakeman::Rails3RoutesProcessor < Brakeman::BaseProcessor
|
|
89
89
|
second_arg = exp.second_arg
|
90
90
|
last_arg = exp.last_arg
|
91
91
|
|
92
|
-
#Check if there is an unrestricted action parameter
|
93
|
-
action_variable = false
|
94
|
-
|
95
92
|
if string? first_arg
|
96
|
-
matcher = first_arg.value
|
97
93
|
|
94
|
+
matcher = first_arg.value
|
98
95
|
if matcher == ':controller(/:action(/:id(.:format)))' or
|
99
|
-
matcher.include? ':controller' and matcher
|
96
|
+
matcher.include? ':controller' and action_route?(matcher) #Default routes
|
100
97
|
@tracker.routes[:allow_all_actions] = first_arg
|
101
98
|
return exp
|
102
|
-
elsif
|
103
|
-
|
99
|
+
elsif action_route?(first_arg)
|
100
|
+
if hash? second_arg and controller_name = hash_access(second_arg, :controller)
|
101
|
+
loose_action(controller_name, "matched") #TODO: Parse verbs
|
102
|
+
end
|
104
103
|
elsif second_arg.nil? and in_controller_block? and not matcher.include? ":"
|
105
104
|
add_route matcher
|
106
105
|
end
|
@@ -123,7 +122,6 @@ class Brakeman::Rails3RoutesProcessor < Brakeman::BaseProcessor
|
|
123
122
|
add_route v
|
124
123
|
end
|
125
124
|
|
126
|
-
action_variable = false
|
127
125
|
when :to
|
128
126
|
if string? v
|
129
127
|
add_route_from_string v[1]
|
@@ -135,10 +133,6 @@ class Brakeman::Rails3RoutesProcessor < Brakeman::BaseProcessor
|
|
135
133
|
end
|
136
134
|
end
|
137
135
|
|
138
|
-
if action_variable
|
139
|
-
@tracker.routes[@current_controller] = :allow_all_actions
|
140
|
-
end
|
141
|
-
|
142
136
|
@current_controller = nil unless in_controller_block?
|
143
137
|
exp
|
144
138
|
end
|
@@ -169,9 +163,17 @@ class Brakeman::Rails3RoutesProcessor < Brakeman::BaseProcessor
|
|
169
163
|
elsif in_controller_block? and symbol? v
|
170
164
|
add_route v
|
171
165
|
end
|
166
|
+
elsif action_route?(first_arg)
|
167
|
+
if hash? second_arg and controller_name = hash_access(second_arg, :controller)
|
168
|
+
loose_action(controller_name, exp.method)
|
169
|
+
end
|
172
170
|
end
|
173
171
|
end
|
174
172
|
elsif string? first_arg
|
173
|
+
if first_arg.value.include? ':controller' and action_route?(first_arg) #Default routes
|
174
|
+
@tracker.routes[:allow_all_actions] = first_arg
|
175
|
+
end
|
176
|
+
|
175
177
|
route = first_arg.value.split "/"
|
176
178
|
if route.length != 2
|
177
179
|
add_route route[0]
|
@@ -287,4 +289,17 @@ class Brakeman::Rails3RoutesProcessor < Brakeman::BaseProcessor
|
|
287
289
|
yield
|
288
290
|
@controller_block = prev_block
|
289
291
|
end
|
292
|
+
|
293
|
+
def action_route? arg
|
294
|
+
if string? arg
|
295
|
+
arg = arg.value
|
296
|
+
end
|
297
|
+
|
298
|
+
arg.is_a? String and (arg.include? ":action" or arg.include? "*action")
|
299
|
+
end
|
300
|
+
|
301
|
+
def loose_action controller_name, verb = "any"
|
302
|
+
self.current_controller = controller_name.value
|
303
|
+
@tracker.routes[@current_controller] = [:allow_all_actions, {:allow_verb => verb}]
|
304
|
+
end
|
290
305
|
end
|
@@ -8,6 +8,8 @@ class Brakeman::LibraryProcessor < Brakeman::BaseProcessor
|
|
8
8
|
super
|
9
9
|
@file_name = nil
|
10
10
|
@alias_processor = Brakeman::AliasProcessor.new tracker
|
11
|
+
@current_module = nil
|
12
|
+
@current_class = nil
|
11
13
|
end
|
12
14
|
|
13
15
|
def process_library src, file_name = nil
|
@@ -17,7 +19,8 @@ class Brakeman::LibraryProcessor < Brakeman::BaseProcessor
|
|
17
19
|
|
18
20
|
def process_class exp
|
19
21
|
name = class_name(exp.class_name)
|
20
|
-
|
22
|
+
parent = class_name exp.parent_name
|
23
|
+
|
21
24
|
if @current_class
|
22
25
|
outer_class = @current_class
|
23
26
|
name = (outer_class[:name].to_s + "::" + name.to_s).to_sym
|
@@ -29,18 +32,20 @@ class Brakeman::LibraryProcessor < Brakeman::BaseProcessor
|
|
29
32
|
|
30
33
|
if @tracker.libs[name]
|
31
34
|
@current_class = @tracker.libs[name]
|
35
|
+
@current_class[:files] << @file_name unless @current_class[:files].include? @file_name
|
36
|
+
@current_class[:src][@file_name] = exp
|
32
37
|
else
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
38
|
+
@current_class = {
|
39
|
+
:name => name,
|
40
|
+
:parent => parent,
|
41
|
+
:includes => [],
|
42
|
+
:public => {},
|
43
|
+
:private => {},
|
44
|
+
:protected => {},
|
45
|
+
:src => { @file_name => exp },
|
46
|
+
:files => [ @file_name ]
|
47
|
+
}
|
48
|
+
|
44
49
|
@tracker.libs[name] = @current_class
|
45
50
|
end
|
46
51
|
|
@@ -59,8 +64,8 @@ class Brakeman::LibraryProcessor < Brakeman::BaseProcessor
|
|
59
64
|
name = class_name(exp.module_name)
|
60
65
|
|
61
66
|
if @current_module
|
62
|
-
|
63
|
-
name = (
|
67
|
+
outer_module = @current_module
|
68
|
+
name = (outer_module[:name].to_s + "::" + name.to_s).to_sym
|
64
69
|
end
|
65
70
|
|
66
71
|
if @current_class
|
@@ -69,22 +74,26 @@ class Brakeman::LibraryProcessor < Brakeman::BaseProcessor
|
|
69
74
|
|
70
75
|
if @tracker.libs[name]
|
71
76
|
@current_module = @tracker.libs[name]
|
77
|
+
@current_module[:files] << @file_name unless @current_module[:files].include? @file_name
|
78
|
+
@current_module[:src][@file_name] = exp
|
72
79
|
else
|
73
|
-
@current_module = {
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
80
|
+
@current_module = {
|
81
|
+
:name => name,
|
82
|
+
:includes => [],
|
83
|
+
:public => {},
|
84
|
+
:private => {},
|
85
|
+
:protected => {},
|
86
|
+
:src => { @file_name => exp },
|
87
|
+
:files => [ @file_name ]
|
88
|
+
}
|
89
|
+
|
81
90
|
@tracker.libs[name] = @current_module
|
82
91
|
end
|
83
92
|
|
84
93
|
exp.body = process_all! exp.body
|
85
94
|
|
86
|
-
if
|
87
|
-
@current_module =
|
95
|
+
if outer_module
|
96
|
+
@current_module = outer_module
|
88
97
|
else
|
89
98
|
@current_module = nil
|
90
99
|
end
|
@@ -97,9 +106,9 @@ class Brakeman::LibraryProcessor < Brakeman::BaseProcessor
|
|
97
106
|
exp.node_type = :methdef
|
98
107
|
|
99
108
|
if @current_class
|
100
|
-
@current_class[:public][exp.method_name] = exp
|
109
|
+
@current_class[:public][exp.method_name] = { :src => exp, :file => @file_name }
|
101
110
|
elsif @current_module
|
102
|
-
@current_module[:public][exp.method_name] = exp
|
111
|
+
@current_module[:public][exp.method_name] = { :src => exp, :file => @file_name }
|
103
112
|
end
|
104
113
|
|
105
114
|
exp
|
@@ -110,9 +119,9 @@ class Brakeman::LibraryProcessor < Brakeman::BaseProcessor
|
|
110
119
|
exp.node_type = :selfdef
|
111
120
|
|
112
121
|
if @current_class
|
113
|
-
@current_class[:public][exp.method_name] = exp
|
122
|
+
@current_class[:public][exp.method_name] = { :src => exp, :file => @file_name }
|
114
123
|
elsif @current_module
|
115
|
-
@current_module[:public][exp.method_name] = exp
|
124
|
+
@current_module[:public][exp.method_name] = { :src => exp, :file => @file_name }
|
116
125
|
end
|
117
126
|
|
118
127
|
exp
|
@@ -6,9 +6,10 @@ class Brakeman::ModelProcessor < Brakeman::BaseProcessor
|
|
6
6
|
ASSOCIATIONS = Set[:belongs_to, :has_one, :has_many, :has_and_belongs_to_many]
|
7
7
|
|
8
8
|
def initialize tracker
|
9
|
-
super
|
10
|
-
@
|
9
|
+
super
|
10
|
+
@current_class = nil
|
11
11
|
@current_method = nil
|
12
|
+
@current_module = nil
|
12
13
|
@visibility = :public
|
13
14
|
@file_name = nil
|
14
15
|
end
|
@@ -21,34 +22,104 @@ class Brakeman::ModelProcessor < Brakeman::BaseProcessor
|
|
21
22
|
|
22
23
|
#s(:class, NAME, PARENT, BODY)
|
23
24
|
def process_class exp
|
24
|
-
name = class_name
|
25
|
+
name = class_name(exp.class_name)
|
26
|
+
parent = class_name(exp.parent_name)
|
27
|
+
|
28
|
+
#If inside an inner class we treat it as a library.
|
29
|
+
if @current_class
|
30
|
+
Brakeman.debug "[Notice] Treating inner class as library: #{name}"
|
31
|
+
Brakeman::LibraryProcessor.new(@tracker).process_library exp, @file_name
|
32
|
+
return exp
|
33
|
+
end
|
25
34
|
|
26
|
-
if @
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
35
|
+
if @current_class
|
36
|
+
outer_class = @current_class
|
37
|
+
name = (outer_class[:name].to_s + "::" + name.to_s).to_sym
|
38
|
+
end
|
39
|
+
|
40
|
+
if @current_module
|
41
|
+
name = (@current_module[:name].to_s + "::" + name.to_s).to_sym
|
42
|
+
end
|
31
43
|
|
32
|
-
|
44
|
+
if @tracker.models[name]
|
45
|
+
@current_class = @tracker.models[name]
|
46
|
+
@current_class[:files] << @file_name unless @current_class[:files].include? @file_name
|
47
|
+
@current_class[:src][@file_name] = exp
|
48
|
+
else
|
49
|
+
@current_class = {
|
50
|
+
:name => name,
|
33
51
|
:parent => parent,
|
34
52
|
:includes => [],
|
35
53
|
:public => {},
|
36
54
|
:private => {},
|
37
55
|
:protected => {},
|
38
56
|
:options => {},
|
57
|
+
:src => { @file_name => exp },
|
39
58
|
:associations => {},
|
40
|
-
:
|
41
|
-
|
42
|
-
|
43
|
-
@
|
44
|
-
|
59
|
+
:files => [ @file_name ]
|
60
|
+
}
|
61
|
+
|
62
|
+
@tracker.models[name] = @current_class
|
63
|
+
end
|
64
|
+
|
65
|
+
exp.body = process_all! exp.body
|
66
|
+
|
67
|
+
if outer_class
|
68
|
+
@current_class = outer_class
|
69
|
+
else
|
70
|
+
@current_class = nil
|
45
71
|
end
|
72
|
+
|
73
|
+
exp
|
74
|
+
end
|
75
|
+
|
76
|
+
def process_module exp
|
77
|
+
name = class_name(exp.class_name)
|
78
|
+
|
79
|
+
if @current_module
|
80
|
+
outer_module = @current_module
|
81
|
+
name = (outer_module[:name].to_s + "::" + name.to_s).to_sym
|
82
|
+
end
|
83
|
+
|
84
|
+
if @current_class
|
85
|
+
name = (@current_class[:name].to_s + "::" + name.to_s).to_sym
|
86
|
+
end
|
87
|
+
|
88
|
+
if @tracker.libs[name]
|
89
|
+
@current_module = @tracker.libs[name]
|
90
|
+
@current_module[:files] << @file_name unless @current_module[:files].include? @file_name
|
91
|
+
@current_module[:src][@file_name] = exp
|
92
|
+
else
|
93
|
+
@current_module = {
|
94
|
+
:name => name,
|
95
|
+
:includes => [],
|
96
|
+
:public => {},
|
97
|
+
:private => {},
|
98
|
+
:protected => {},
|
99
|
+
:options => {},
|
100
|
+
:src => { @file_name => exp },
|
101
|
+
:associations => {},
|
102
|
+
:files => [ @file_name ]
|
103
|
+
}
|
104
|
+
|
105
|
+
@tracker.libs[name] = @current_module
|
106
|
+
end
|
107
|
+
|
108
|
+
exp.body = process_all! exp.body
|
109
|
+
|
110
|
+
if outer_module
|
111
|
+
@current_module = outer_module
|
112
|
+
else
|
113
|
+
@current_module = nil
|
114
|
+
end
|
115
|
+
|
116
|
+
exp
|
46
117
|
end
|
47
118
|
|
48
119
|
#Handle calls outside of methods,
|
49
120
|
#such as include, attr_accessible, private, etc.
|
50
121
|
def process_call exp
|
51
|
-
return exp unless @
|
122
|
+
return exp unless @current_class
|
52
123
|
target = exp.target
|
53
124
|
if sexp? target
|
54
125
|
target = process target
|
@@ -65,36 +136,36 @@ class Brakeman::ModelProcessor < Brakeman::BaseProcessor
|
|
65
136
|
when :private, :protected, :public
|
66
137
|
@visibility = method
|
67
138
|
when :attr_accessible
|
68
|
-
@
|
139
|
+
@current_class[:attr_accessible] ||= []
|
69
140
|
else
|
70
141
|
#??
|
71
142
|
end
|
72
143
|
else
|
73
144
|
case method
|
74
145
|
when :include
|
75
|
-
@
|
146
|
+
@current_class[:includes] << class_name(first_arg) if @current_class
|
76
147
|
when :attr_accessible
|
77
|
-
@
|
148
|
+
@current_class[:attr_accessible] ||= []
|
78
149
|
args = []
|
79
150
|
|
80
151
|
exp.each_arg do |e|
|
81
152
|
if node_type? e, :lit
|
82
153
|
args << e.value
|
83
154
|
elsif hash? e
|
84
|
-
@
|
85
|
-
@
|
155
|
+
@current_class[:options][:role_accessible] ||= []
|
156
|
+
@current_class[:options][:role_accessible].concat args
|
86
157
|
end
|
87
158
|
end
|
88
159
|
|
89
|
-
@
|
160
|
+
@current_class[:attr_accessible].concat args
|
90
161
|
else
|
91
|
-
if @
|
162
|
+
if @current_class
|
92
163
|
if ASSOCIATIONS.include? method
|
93
|
-
@
|
94
|
-
@
|
164
|
+
@current_class[:associations][method] ||= []
|
165
|
+
@current_class[:associations][method].concat exp.args
|
95
166
|
else
|
96
|
-
@
|
97
|
-
@
|
167
|
+
@current_class[:options][method] ||= []
|
168
|
+
@current_class[:options][method] << exp.arglist.line(exp.line)
|
98
169
|
end
|
99
170
|
end
|
100
171
|
end
|
@@ -109,27 +180,36 @@ class Brakeman::ModelProcessor < Brakeman::BaseProcessor
|
|
109
180
|
|
110
181
|
#Add method definition to tracker
|
111
182
|
def process_defn exp
|
112
|
-
return exp unless @
|
183
|
+
return exp unless @current_class
|
113
184
|
name = exp.method_name
|
114
185
|
|
115
186
|
@current_method = name
|
116
187
|
res = Sexp.new :methdef, name, exp.formal_args, *process_all!(exp.body)
|
117
188
|
res.line(exp.line)
|
118
189
|
@current_method = nil
|
119
|
-
|
120
|
-
|
121
|
-
|
190
|
+
|
191
|
+
if @current_class
|
192
|
+
@current_class[@visibility][name] = { :src => res, :file => @file_name }
|
193
|
+
elsif @current_module
|
194
|
+
@current_module[@visibility][name] = { :src => res, :file => @file_name }
|
122
195
|
end
|
196
|
+
|
123
197
|
res
|
124
198
|
end
|
125
199
|
|
126
200
|
#Add method definition to tracker
|
127
201
|
def process_defs exp
|
128
|
-
return exp unless @
|
202
|
+
return exp unless @current_class
|
129
203
|
name = exp.method_name
|
130
204
|
|
131
205
|
if exp[1].node_type == :self
|
132
|
-
|
206
|
+
if @current_class
|
207
|
+
target = @current_class[:name]
|
208
|
+
elsif @current_module
|
209
|
+
target = @current_module
|
210
|
+
else
|
211
|
+
target = nil
|
212
|
+
end
|
133
213
|
else
|
134
214
|
target = class_name exp[1]
|
135
215
|
end
|
@@ -138,8 +218,11 @@ class Brakeman::ModelProcessor < Brakeman::BaseProcessor
|
|
138
218
|
res = Sexp.new :selfdef, target, name, exp.formal_args, *process_all!(exp.body)
|
139
219
|
res.line(exp.line)
|
140
220
|
@current_method = nil
|
141
|
-
|
142
|
-
|
221
|
+
|
222
|
+
if @current_class
|
223
|
+
@current_class[@visibility][name] = { :src => res, :file => @file_name }
|
224
|
+
elsif @current_module
|
225
|
+
@current_module[@visibility][name] = { :src => res, :file => @file_name }
|
143
226
|
end
|
144
227
|
res
|
145
228
|
end
|
@@ -39,7 +39,7 @@ class Brakeman::Report::Base
|
|
39
39
|
name = name.to_sym
|
40
40
|
c = tracker.controllers[name]
|
41
41
|
|
42
|
-
if tracker.routes
|
42
|
+
if tracker.routes.include? :allow_all_actions or (tracker.routes[name] and tracker.routes[name].include? :allow_all_actions)
|
43
43
|
routes = c[:public].keys.map{|e| e.to_s}.sort.join(", ")
|
44
44
|
elsif tracker.routes[name].nil?
|
45
45
|
#No routes defined for this controller.
|