brakeman 2.5.0 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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.
|