brakeman 1.2.1 → 1.2.2

Sign up to get free protection for your applications and to get access to all the features.
data/lib/brakeman.rb CHANGED
@@ -48,7 +48,9 @@ module Brakeman
48
48
  @quiet = !!options[:quiet]
49
49
  @debug = !!options[:debug]
50
50
 
51
- options[:report_progress] = !@quiet
51
+ if @quiet
52
+ options[:report_progress] = false
53
+ end
52
54
 
53
55
  scan options
54
56
  end
@@ -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
- raise "Unhandled resource option: #{option}"
131
+ Brakeman.notify "[Notice] Unhandled resource option: #{option}"
132
132
  end
133
133
  end
134
134
  end
@@ -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}
@@ -1,3 +1,3 @@
1
1
  module Brakeman
2
- Version = "1.2.1"
2
+ Version = "1.2.2"
3
3
  end
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
- version: 1.2.1
5
- prerelease:
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
- date: 2012-01-20 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
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
- requirement: &76221240 !ruby/object:Gem::Requirement
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
17
24
  none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
21
- version: '0'
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ version: "0"
22
31
  type: :runtime
23
- prerelease: false
24
- version_requirements: *76221240
25
- - !ruby/object:Gem::Dependency
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
26
34
  name: i18n
27
- requirement: &76220920 !ruby/object:Gem::Requirement
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
28
37
  none: false
29
- requirements:
30
- - - ! '>='
31
- - !ruby/object:Gem::Version
32
- version: '0'
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
43
+ version: "0"
33
44
  type: :runtime
34
- prerelease: false
35
- version_requirements: *76220920
36
- - !ruby/object:Gem::Dependency
45
+ version_requirements: *id002
46
+ - !ruby/object:Gem::Dependency
37
47
  name: ruby2ruby
38
- requirement: &76220320 !ruby/object:Gem::Requirement
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
- version: '1.2'
53
+ - !ruby/object:Gem::Version
54
+ segments:
55
+ - 1
56
+ - 2
57
+ version: "1.2"
44
58
  type: :runtime
45
- prerelease: false
46
- version_requirements: *76220320
47
- - !ruby/object:Gem::Dependency
59
+ version_requirements: *id003
60
+ - !ruby/object:Gem::Dependency
48
61
  name: ruport
49
- requirement: &76219720 !ruby/object:Gem::Requirement
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
- version: '1.6'
67
+ - !ruby/object:Gem::Version
68
+ segments:
69
+ - 1
70
+ - 6
71
+ version: "1.6"
55
72
  type: :runtime
56
- prerelease: false
57
- version_requirements: *76219720
58
- - !ruby/object:Gem::Dependency
73
+ version_requirements: *id004
74
+ - !ruby/object:Gem::Dependency
59
75
  name: erubis
60
- requirement: &76943790 !ruby/object:Gem::Requirement
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
- version: '2.6'
81
+ - !ruby/object:Gem::Version
82
+ segments:
83
+ - 2
84
+ - 6
85
+ version: "2.6"
66
86
  type: :runtime
67
- prerelease: false
68
- version_requirements: *76943790
69
- - !ruby/object:Gem::Dependency
87
+ version_requirements: *id005
88
+ - !ruby/object:Gem::Dependency
70
89
  name: haml
71
- requirement: &76943560 !ruby/object:Gem::Requirement
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
- version: '3.0'
95
+ - !ruby/object:Gem::Version
96
+ segments:
97
+ - 3
98
+ - 0
99
+ version: "3.0"
77
100
  type: :runtime
78
- prerelease: false
79
- version_requirements: *76943560
80
- - !ruby/object:Gem::Dependency
101
+ version_requirements: *id006
102
+ - !ruby/object:Gem::Dependency
81
103
  name: sass
82
- requirement: &76943330 !ruby/object:Gem::Requirement
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
- version: '3.0'
109
+ - !ruby/object:Gem::Version
110
+ segments:
111
+ - 3
112
+ - 0
113
+ version: "3.0"
88
114
  type: :runtime
89
- prerelease: false
90
- version_requirements: *76943330
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
- files:
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
- require_paths:
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
- version: '0'
183
- required_rubygems_version: !ruby/object:Gem::Requirement
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
- version: '0'
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.8.10
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
+