brakeman 1.2.1 → 1.2.2
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.
data/lib/brakeman.rb
CHANGED
@@ -44,12 +44,6 @@ class Brakeman::CheckCrossSiteScripting < Brakeman::BaseCheck
|
|
44
44
|
@models = tracker.models.keys
|
45
45
|
@inspect_arguments = tracker.options[:check_arguments]
|
46
46
|
|
47
|
-
if version_between?("2.0.0", "2.9.9") and not tracker.config[:escape_html]
|
48
|
-
link_to_check = Brakeman::CheckLinkTo.new(tracker)
|
49
|
-
link_to_check.run_check
|
50
|
-
warnings.concat link_to_check.warnings unless link_to_check.warnings.empty?
|
51
|
-
end
|
52
|
-
|
53
47
|
@known_dangerous = Set.new([:truncate, :concat])
|
54
48
|
|
55
49
|
if version_between? "2.0.0", "3.0.5"
|
@@ -264,121 +258,3 @@ class Brakeman::CheckCrossSiteScripting < Brakeman::BaseCheck
|
|
264
258
|
exp[1].node_type == :call and exp[1][2] == :raw
|
265
259
|
end
|
266
260
|
end
|
267
|
-
|
268
|
-
#This _only_ checks calls to link_to
|
269
|
-
class Brakeman::CheckLinkTo < Brakeman::CheckCrossSiteScripting
|
270
|
-
def run_check
|
271
|
-
@ignore_methods = Set.new([:button_to, :check_box, :escapeHTML, :escape_once,
|
272
|
-
:field_field, :fields_for, :h, :hidden_field,
|
273
|
-
:hidden_field, :hidden_field_tag, :image_tag, :label,
|
274
|
-
:mail_to, :radio_button, :select,
|
275
|
-
:submit_tag, :text_area, :text_field,
|
276
|
-
:text_field_tag, :url_encode, :url_for,
|
277
|
-
:will_paginate] ).merge tracker.options[:safe_methods]
|
278
|
-
|
279
|
-
@known_dangerous = []
|
280
|
-
#Ideally, I think this should also check to see if people are setting
|
281
|
-
#:escape => false
|
282
|
-
methods = tracker.find_call :target => false, :method => :link_to
|
283
|
-
|
284
|
-
@models = tracker.models.keys
|
285
|
-
@inspect_arguments = tracker.options[:check_arguments]
|
286
|
-
|
287
|
-
methods.each do |call|
|
288
|
-
process_result call
|
289
|
-
end
|
290
|
-
end
|
291
|
-
|
292
|
-
def process_result result
|
293
|
-
#Have to make a copy of this, otherwise it will be changed to
|
294
|
-
#an ignored method call by the code above.
|
295
|
-
call = result[:call] = result[:call].dup
|
296
|
-
|
297
|
-
@matched = false
|
298
|
-
|
299
|
-
return if call[3][1].nil?
|
300
|
-
|
301
|
-
#Only check first argument for +link_to+, as the second
|
302
|
-
#will *usually* be a record or escaped.
|
303
|
-
first_arg = process call[3][1]
|
304
|
-
|
305
|
-
type, match = has_immediate_user_input? first_arg
|
306
|
-
|
307
|
-
if type
|
308
|
-
case type
|
309
|
-
when :params
|
310
|
-
message = "Unescaped parameter value in link_to"
|
311
|
-
when :cookies
|
312
|
-
message = "Unescaped cookie value in link_to"
|
313
|
-
else
|
314
|
-
message = "Unescaped user input value in link_to"
|
315
|
-
end
|
316
|
-
|
317
|
-
unless duplicate? result
|
318
|
-
add_result result
|
319
|
-
|
320
|
-
warn :result => result,
|
321
|
-
:warning_type => "Cross Site Scripting",
|
322
|
-
:message => message,
|
323
|
-
:confidence => CONFIDENCE[:high]
|
324
|
-
end
|
325
|
-
|
326
|
-
elsif not tracker.options[:ignore_model_output] and match = has_immediate_model?(first_arg)
|
327
|
-
method = match[2]
|
328
|
-
|
329
|
-
unless duplicate? result or IGNORE_MODEL_METHODS.include? method
|
330
|
-
add_result result
|
331
|
-
|
332
|
-
if MODEL_METHODS.include? method or method.to_s =~ /^find_by/
|
333
|
-
confidence = CONFIDENCE[:high]
|
334
|
-
else
|
335
|
-
confidence = CONFIDENCE[:med]
|
336
|
-
end
|
337
|
-
|
338
|
-
warn :result => result,
|
339
|
-
:warning_type => "Cross Site Scripting",
|
340
|
-
:message => "Unescaped model attribute in link_to",
|
341
|
-
:confidence => confidence
|
342
|
-
end
|
343
|
-
|
344
|
-
elsif @matched
|
345
|
-
if @matched == :model and not tracker.options[:ignore_model_output]
|
346
|
-
message = "Unescaped model attribute in link_to"
|
347
|
-
elsif @matched == :params
|
348
|
-
message = "Unescaped parameter value in link_to"
|
349
|
-
end
|
350
|
-
|
351
|
-
if message and not duplicate? result
|
352
|
-
add_result result
|
353
|
-
|
354
|
-
warn :result => result,
|
355
|
-
:warning_type => "Cross Site Scripting",
|
356
|
-
:message => message,
|
357
|
-
:confidence => CONFIDENCE[:med]
|
358
|
-
end
|
359
|
-
end
|
360
|
-
end
|
361
|
-
|
362
|
-
def process_call exp
|
363
|
-
@mark = true
|
364
|
-
actually_process_call exp
|
365
|
-
exp
|
366
|
-
end
|
367
|
-
|
368
|
-
def actually_process_call exp
|
369
|
-
return if @matched
|
370
|
-
|
371
|
-
target = exp[1]
|
372
|
-
if sexp? target
|
373
|
-
target = process target.dup
|
374
|
-
end
|
375
|
-
|
376
|
-
#Bare records create links to the model resource,
|
377
|
-
#not a string that could have injection
|
378
|
-
if model_name? target and context == [:call, :arglist]
|
379
|
-
return exp
|
380
|
-
end
|
381
|
-
|
382
|
-
super
|
383
|
-
end
|
384
|
-
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'brakeman/checks/check_cross_site_scripting'
|
2
|
+
|
3
|
+
#Checks for calls to link_to in versions of Ruby where link_to did not
|
4
|
+
#escape the first argument.
|
5
|
+
#
|
6
|
+
#See https://rails.lighthouseapp.com/projects/8994/tickets/3518-link_to-doesnt-escape-its-input
|
7
|
+
class Brakeman::CheckLinkTo < Brakeman::CheckCrossSiteScripting
|
8
|
+
Brakeman::Checks.add self
|
9
|
+
|
10
|
+
def run_check
|
11
|
+
return unless version_between?("2.0.0", "2.9.9") and not tracker.config[:escape_html]
|
12
|
+
|
13
|
+
@ignore_methods = Set.new([:button_to, :check_box, :escapeHTML, :escape_once,
|
14
|
+
:field_field, :fields_for, :h, :hidden_field,
|
15
|
+
:hidden_field, :hidden_field_tag, :image_tag, :label,
|
16
|
+
:mail_to, :radio_button, :select,
|
17
|
+
:submit_tag, :text_area, :text_field,
|
18
|
+
:text_field_tag, :url_encode, :url_for,
|
19
|
+
:will_paginate] ).merge tracker.options[:safe_methods]
|
20
|
+
|
21
|
+
@known_dangerous = []
|
22
|
+
#Ideally, I think this should also check to see if people are setting
|
23
|
+
#:escape => false
|
24
|
+
methods = tracker.find_call :target => false, :method => :link_to
|
25
|
+
|
26
|
+
@models = tracker.models.keys
|
27
|
+
@inspect_arguments = tracker.options[:check_arguments]
|
28
|
+
|
29
|
+
methods.each do |call|
|
30
|
+
process_result call
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def process_result result
|
35
|
+
#Have to make a copy of this, otherwise it will be changed to
|
36
|
+
#an ignored method call by the code above.
|
37
|
+
call = result[:call] = result[:call].dup
|
38
|
+
|
39
|
+
@matched = false
|
40
|
+
|
41
|
+
return if call[3][1].nil?
|
42
|
+
|
43
|
+
#Only check first argument for +link_to+, as the second
|
44
|
+
#will *usually* be a record or escaped.
|
45
|
+
first_arg = process call[3][1]
|
46
|
+
|
47
|
+
type, match = has_immediate_user_input? first_arg
|
48
|
+
|
49
|
+
if type
|
50
|
+
case type
|
51
|
+
when :params
|
52
|
+
message = "Unescaped parameter value in link_to"
|
53
|
+
when :cookies
|
54
|
+
message = "Unescaped cookie value in link_to"
|
55
|
+
else
|
56
|
+
message = "Unescaped user input value in link_to"
|
57
|
+
end
|
58
|
+
|
59
|
+
unless duplicate? result
|
60
|
+
add_result result
|
61
|
+
|
62
|
+
warn :result => result,
|
63
|
+
:warning_type => "Cross Site Scripting",
|
64
|
+
:message => message,
|
65
|
+
:confidence => CONFIDENCE[:high]
|
66
|
+
end
|
67
|
+
|
68
|
+
elsif not tracker.options[:ignore_model_output] and match = has_immediate_model?(first_arg)
|
69
|
+
method = match[2]
|
70
|
+
|
71
|
+
unless duplicate? result or IGNORE_MODEL_METHODS.include? method
|
72
|
+
add_result result
|
73
|
+
|
74
|
+
if MODEL_METHODS.include? method or method.to_s =~ /^find_by/
|
75
|
+
confidence = CONFIDENCE[:high]
|
76
|
+
else
|
77
|
+
confidence = CONFIDENCE[:med]
|
78
|
+
end
|
79
|
+
|
80
|
+
warn :result => result,
|
81
|
+
:warning_type => "Cross Site Scripting",
|
82
|
+
:message => "Unescaped model attribute in link_to",
|
83
|
+
:confidence => confidence
|
84
|
+
end
|
85
|
+
|
86
|
+
elsif @matched
|
87
|
+
if @matched == :model and not tracker.options[:ignore_model_output]
|
88
|
+
message = "Unescaped model attribute in link_to"
|
89
|
+
elsif @matched == :params
|
90
|
+
message = "Unescaped parameter value in link_to"
|
91
|
+
end
|
92
|
+
|
93
|
+
if message and not duplicate? result
|
94
|
+
add_result result
|
95
|
+
|
96
|
+
warn :result => result,
|
97
|
+
:warning_type => "Cross Site Scripting",
|
98
|
+
:message => message,
|
99
|
+
:confidence => CONFIDENCE[:med]
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def process_call exp
|
105
|
+
@mark = true
|
106
|
+
actually_process_call exp
|
107
|
+
exp
|
108
|
+
end
|
109
|
+
|
110
|
+
def actually_process_call exp
|
111
|
+
return if @matched
|
112
|
+
|
113
|
+
target = exp[1]
|
114
|
+
if sexp? target
|
115
|
+
target = process target.dup
|
116
|
+
end
|
117
|
+
|
118
|
+
#Bare records create links to the model resource,
|
119
|
+
#not a string that could have injection
|
120
|
+
if model_name? target and context == [:call, :arglist]
|
121
|
+
return exp
|
122
|
+
end
|
123
|
+
|
124
|
+
super
|
125
|
+
end
|
126
|
+
end
|
@@ -69,7 +69,7 @@ class Brakeman::Rails2RoutesProcessor < Brakeman::BaseProcessor
|
|
69
69
|
process_namespace exp
|
70
70
|
when :resources, :resource
|
71
71
|
process_resources exp[1][3][1..-1]
|
72
|
-
process_default exp[3]
|
72
|
+
process_default exp[3] if exp[3]
|
73
73
|
when :with_options
|
74
74
|
process_with_options exp
|
75
75
|
end
|
@@ -111,7 +111,7 @@ class Brakeman::Rails2RoutesProcessor < Brakeman::BaseProcessor
|
|
111
111
|
hash_iterate(exp) do |option, value|
|
112
112
|
case option[1]
|
113
113
|
when :controller, :requirements, :singular, :path_prefix, :as,
|
114
|
-
:path_names, :shallow, :name_prefix
|
114
|
+
:path_names, :shallow, :name_prefix, :member_path, :nested_member_path
|
115
115
|
#should be able to skip
|
116
116
|
when :collection, :member, :new
|
117
117
|
process_collection value
|
@@ -128,7 +128,7 @@ class Brakeman::Rails2RoutesProcessor < Brakeman::BaseProcessor
|
|
128
128
|
when :except
|
129
129
|
process_option_except value
|
130
130
|
else
|
131
|
-
|
131
|
+
Brakeman.notify "[Notice] Unhandled resource option: #{option}"
|
132
132
|
end
|
133
133
|
end
|
134
134
|
end
|
data/lib/brakeman/rescanner.rb
CHANGED
@@ -245,6 +245,14 @@ class Brakeman::RescanReport
|
|
245
245
|
@diff ||= @new_results.diff(@old_results)
|
246
246
|
end
|
247
247
|
|
248
|
+
#Returns an array of warnings which were in the old report and the new report
|
249
|
+
def existing_warnings
|
250
|
+
@old ||= all_warnings.select do |w|
|
251
|
+
not new_warnings.include? w
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
#Output total, fixed, and new warnings
|
248
256
|
def to_s
|
249
257
|
<<-OUTPUT
|
250
258
|
Total warnings: #{all_warnings.length}
|
data/lib/brakeman/version.rb
CHANGED
metadata
CHANGED
@@ -1,101 +1,127 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: brakeman
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 1
|
7
|
+
- 2
|
8
|
+
- 2
|
9
|
+
version: 1.2.2
|
6
10
|
platform: ruby
|
7
|
-
authors:
|
11
|
+
authors:
|
8
12
|
- Justin Collins
|
9
13
|
autorequire:
|
10
14
|
bindir: bin
|
11
15
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
16
|
+
|
17
|
+
date: 2012-01-26 00:00:00 -08:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
15
21
|
name: activesupport
|
16
|
-
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
17
24
|
none: false
|
18
|
-
requirements:
|
19
|
-
- -
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
version: "0"
|
22
31
|
type: :runtime
|
23
|
-
|
24
|
-
|
25
|
-
- !ruby/object:Gem::Dependency
|
32
|
+
version_requirements: *id001
|
33
|
+
- !ruby/object:Gem::Dependency
|
26
34
|
name: i18n
|
27
|
-
|
35
|
+
prerelease: false
|
36
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
28
37
|
none: false
|
29
|
-
requirements:
|
30
|
-
- -
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 0
|
43
|
+
version: "0"
|
33
44
|
type: :runtime
|
34
|
-
|
35
|
-
|
36
|
-
- !ruby/object:Gem::Dependency
|
45
|
+
version_requirements: *id002
|
46
|
+
- !ruby/object:Gem::Dependency
|
37
47
|
name: ruby2ruby
|
38
|
-
|
48
|
+
prerelease: false
|
49
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
39
50
|
none: false
|
40
|
-
requirements:
|
51
|
+
requirements:
|
41
52
|
- - ~>
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
segments:
|
55
|
+
- 1
|
56
|
+
- 2
|
57
|
+
version: "1.2"
|
44
58
|
type: :runtime
|
45
|
-
|
46
|
-
|
47
|
-
- !ruby/object:Gem::Dependency
|
59
|
+
version_requirements: *id003
|
60
|
+
- !ruby/object:Gem::Dependency
|
48
61
|
name: ruport
|
49
|
-
|
62
|
+
prerelease: false
|
63
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
50
64
|
none: false
|
51
|
-
requirements:
|
65
|
+
requirements:
|
52
66
|
- - ~>
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
segments:
|
69
|
+
- 1
|
70
|
+
- 6
|
71
|
+
version: "1.6"
|
55
72
|
type: :runtime
|
56
|
-
|
57
|
-
|
58
|
-
- !ruby/object:Gem::Dependency
|
73
|
+
version_requirements: *id004
|
74
|
+
- !ruby/object:Gem::Dependency
|
59
75
|
name: erubis
|
60
|
-
|
76
|
+
prerelease: false
|
77
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
61
78
|
none: false
|
62
|
-
requirements:
|
79
|
+
requirements:
|
63
80
|
- - ~>
|
64
|
-
- !ruby/object:Gem::Version
|
65
|
-
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
segments:
|
83
|
+
- 2
|
84
|
+
- 6
|
85
|
+
version: "2.6"
|
66
86
|
type: :runtime
|
67
|
-
|
68
|
-
|
69
|
-
- !ruby/object:Gem::Dependency
|
87
|
+
version_requirements: *id005
|
88
|
+
- !ruby/object:Gem::Dependency
|
70
89
|
name: haml
|
71
|
-
|
90
|
+
prerelease: false
|
91
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
72
92
|
none: false
|
73
|
-
requirements:
|
93
|
+
requirements:
|
74
94
|
- - ~>
|
75
|
-
- !ruby/object:Gem::Version
|
76
|
-
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
segments:
|
97
|
+
- 3
|
98
|
+
- 0
|
99
|
+
version: "3.0"
|
77
100
|
type: :runtime
|
78
|
-
|
79
|
-
|
80
|
-
- !ruby/object:Gem::Dependency
|
101
|
+
version_requirements: *id006
|
102
|
+
- !ruby/object:Gem::Dependency
|
81
103
|
name: sass
|
82
|
-
|
104
|
+
prerelease: false
|
105
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
83
106
|
none: false
|
84
|
-
requirements:
|
107
|
+
requirements:
|
85
108
|
- - ~>
|
86
|
-
- !ruby/object:Gem::Version
|
87
|
-
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
segments:
|
111
|
+
- 3
|
112
|
+
- 0
|
113
|
+
version: "3.0"
|
88
114
|
type: :runtime
|
89
|
-
|
90
|
-
|
91
|
-
description: Brakeman detects security vulnerabilities in Ruby on Rails applications
|
92
|
-
via static analysis.
|
115
|
+
version_requirements: *id007
|
116
|
+
description: Brakeman detects security vulnerabilities in Ruby on Rails applications via static analysis.
|
93
117
|
email:
|
94
|
-
executables:
|
118
|
+
executables:
|
95
119
|
- brakeman
|
96
120
|
extensions: []
|
121
|
+
|
97
122
|
extra_rdoc_files: []
|
98
|
-
|
123
|
+
|
124
|
+
files:
|
99
125
|
- bin/brakeman
|
100
126
|
- WARNING_TYPES
|
101
127
|
- FEATURES
|
@@ -147,6 +173,7 @@ files:
|
|
147
173
|
- lib/brakeman/checks/check_evaluation.rb
|
148
174
|
- lib/brakeman/checks/check_quote_table_name.rb
|
149
175
|
- lib/brakeman/checks/check_validation_regex.rb
|
176
|
+
- lib/brakeman/checks/check_link_to.rb
|
150
177
|
- lib/brakeman/checks/check_execute.rb
|
151
178
|
- lib/brakeman/checks/check_filter_skipping.rb
|
152
179
|
- lib/brakeman/checks/check_mail_to.rb
|
@@ -168,28 +195,37 @@ files:
|
|
168
195
|
- lib/brakeman/processor.rb
|
169
196
|
- lib/brakeman.rb
|
170
197
|
- lib/brakeman/format/style.css
|
198
|
+
has_rdoc: true
|
171
199
|
homepage: http://brakemanscanner.org
|
172
200
|
licenses: []
|
201
|
+
|
173
202
|
post_install_message:
|
174
203
|
rdoc_options: []
|
175
|
-
|
204
|
+
|
205
|
+
require_paths:
|
176
206
|
- lib
|
177
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
207
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
178
208
|
none: false
|
179
|
-
requirements:
|
180
|
-
- -
|
181
|
-
- !ruby/object:Gem::Version
|
182
|
-
|
183
|
-
|
209
|
+
requirements:
|
210
|
+
- - ">="
|
211
|
+
- !ruby/object:Gem::Version
|
212
|
+
segments:
|
213
|
+
- 0
|
214
|
+
version: "0"
|
215
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
184
216
|
none: false
|
185
|
-
requirements:
|
186
|
-
- -
|
187
|
-
- !ruby/object:Gem::Version
|
188
|
-
|
217
|
+
requirements:
|
218
|
+
- - ">="
|
219
|
+
- !ruby/object:Gem::Version
|
220
|
+
segments:
|
221
|
+
- 0
|
222
|
+
version: "0"
|
189
223
|
requirements: []
|
224
|
+
|
190
225
|
rubyforge_project:
|
191
|
-
rubygems_version: 1.
|
226
|
+
rubygems_version: 1.3.7
|
192
227
|
signing_key:
|
193
228
|
specification_version: 3
|
194
229
|
summary: Security vulnerability scanner for Ruby on Rails.
|
195
230
|
test_files: []
|
231
|
+
|