brakeman 1.2.0 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -6,9 +6,15 @@ It targets Rails versions 2.x and 3.x.
6
6
 
7
7
  There is also a [plugin available](http://brakemanscanner.org/docs/jenkins/) for Jenkins/Hudson.
8
8
 
9
- # Homepage
9
+ For even more continuous testing, try the [Guard plugin](https://github.com/oreoshake/guard-brakeman).
10
10
 
11
- http://brakemanscanner.org/
11
+ # Homepage/News
12
+
13
+ Website: http://brakemanscanner.org/
14
+
15
+ Twitter: http://twitter.com/brakemanscanner
16
+
17
+ Mailing list: brakeman@librelist.com
12
18
 
13
19
  # Installation
14
20
 
@@ -8,6 +8,9 @@ module Brakeman
8
8
  #option is set
9
9
  Warnings_Found_Exit_Code = 3
10
10
 
11
+ @debug = false
12
+ @quiet = false
13
+
11
14
  #Run Brakeman scan. Returns Tracker object.
12
15
  #
13
16
  #Options:
@@ -42,14 +45,15 @@ module Brakeman
42
45
  def self.run options
43
46
  options = set_options options
44
47
 
45
- if options[:quiet]
46
- options[:report_progress] = false
47
- $VERBOSE = nil
48
- end
48
+ @quiet = !!options[:quiet]
49
+ @debug = !!options[:debug]
50
+
51
+ options[:report_progress] = !@quiet
49
52
 
50
53
  scan options
51
54
  end
52
55
 
56
+ #Sets up options for run, checks given application path
53
57
  def self.set_options options
54
58
  if options.is_a? String
55
59
  options = { :app_path => options }
@@ -67,12 +71,13 @@ module Brakeman
67
71
 
68
72
  if File.exist? app_path + "/script/rails"
69
73
  options[:rails3] = true
70
- warn "[Notice] Detected Rails 3 application"
74
+ notify "[Notice] Detected Rails 3 application"
71
75
  end
72
76
 
73
77
  options
74
78
  end
75
79
 
80
+ #Load options from YAML file
76
81
  def self.load_options config_file
77
82
  config_file ||= ""
78
83
 
@@ -84,7 +89,7 @@ module Brakeman
84
89
  "#{File.expand_path(File.dirname(__FILE__))}/../lib/config.yaml"].each do |f|
85
90
 
86
91
  if File.exist? f and not File.directory? f
87
- warn "[Notice] Using configuration in #{f}" unless options[:quiet]
92
+ notify "[Notice] Using configuration in #{f}"
88
93
  options = YAML.load_file f
89
94
  options.each do |k,v|
90
95
  if v.is_a? Array
@@ -99,6 +104,7 @@ module Brakeman
99
104
  return {}
100
105
  end
101
106
 
107
+ #Default set of options
102
108
  def self.get_defaults
103
109
  { :skip_checks => Set.new,
104
110
  :check_arguments => true,
@@ -116,6 +122,8 @@ module Brakeman
116
122
  }
117
123
  end
118
124
 
125
+ #Determine output format based on options[:output_format]
126
+ #or options[:output_file]
119
127
  def self.get_output_format options
120
128
  #Set output format
121
129
  if options[:output_format]
@@ -147,6 +155,7 @@ module Brakeman
147
155
  end
148
156
  end
149
157
 
158
+ #Output list of checks (for `-k` option)
150
159
  def self.list_checks
151
160
  require 'brakeman/scanner'
152
161
  $stderr.puts "Available Checks:"
@@ -154,6 +163,9 @@ module Brakeman
154
163
  $stderr.puts Checks.checks.map { |c| c.to_s.match(/^Brakeman::(.*)$/)[1] }.sort.join "\n"
155
164
  end
156
165
 
166
+ #Installs Rake task for running Brakeman,
167
+ #which basically means copying `lib/brakeman/brakeman.rake` to
168
+ #`lib/tasks/brakeman.rake` in the current Rails application.
157
169
  def self.install_rake_task
158
170
  if not File.exists? "Rakefile"
159
171
  abort "No Rakefile detected"
@@ -164,7 +176,7 @@ module Brakeman
164
176
  require 'fileutils'
165
177
 
166
178
  if not File.exists? "lib/tasks"
167
- warn "Creating lib/tasks"
179
+ notify "Creating lib/tasks"
168
180
  FileUtils.mkdir_p "lib/tasks"
169
181
  end
170
182
 
@@ -173,13 +185,14 @@ module Brakeman
173
185
  FileUtils.cp "#{path}/brakeman/brakeman.rake", "lib/tasks/brakeman.rake"
174
186
 
175
187
  if File.exists? "lib/tasks/brakeman.rake"
176
- warn "Task created in lib/tasks/brakeman.rake"
177
- warn "Usage: rake brakeman:run[output_file]"
188
+ notify "Task created in lib/tasks/brakeman.rake"
189
+ notify "Usage: rake brakeman:run[output_file]"
178
190
  else
179
- warn "Could not create task"
191
+ notify "Could not create task"
180
192
  end
181
193
  end
182
194
 
195
+ #Output configuration to YAML
183
196
  def self.dump_config options
184
197
  if options[:create_config].is_a? String
185
198
  file = options[:create_config]
@@ -206,9 +219,10 @@ module Brakeman
206
219
  exit
207
220
  end
208
221
 
222
+ #Run a scan. Generally called from Brakeman.run instead of directly.
209
223
  def self.scan options
210
224
  #Load scanner
211
- warn "Loading scanner..."
225
+ notify "Loading scanner..."
212
226
 
213
227
  begin
214
228
  require 'brakeman/scanner'
@@ -219,27 +233,27 @@ module Brakeman
219
233
  #Start scanning
220
234
  scanner = Scanner.new options
221
235
 
222
- warn "[Notice] Using Ruby #{RUBY_VERSION}. Please make sure this matches the one used to run your Rails application."
236
+ notify "[Notice] Using Ruby #{RUBY_VERSION}. Please make sure this matches the one used to run your Rails application."
223
237
 
224
- warn "Processing application in #{options[:app_path]}"
238
+ notify "Processing application in #{options[:app_path]}"
225
239
  tracker = scanner.process
226
240
 
227
241
  if options[:parallel_checks]
228
- warn "Running checks in parallel..."
242
+ notify "Running checks in parallel..."
229
243
  else
230
- warn "Runnning checks..."
244
+ notify "Runnning checks..."
231
245
  end
232
246
  tracker.run_checks
233
247
 
234
248
  if options[:output_file]
235
- warn "Generating report..."
249
+ notify "Generating report..."
236
250
 
237
251
  File.open options[:output_file], "w" do |f|
238
252
  f.puts tracker.report.send(options[:output_format])
239
253
  end
240
- warn "Report saved in '#{options[:output_file]}'"
254
+ notify "Report saved in '#{options[:output_file]}'"
241
255
  elsif options[:print_report]
242
- warn "Generating report..."
256
+ notify "Generating report..."
243
257
 
244
258
  puts tracker.report.send(options[:output_format])
245
259
  end
@@ -256,9 +270,33 @@ module Brakeman
256
270
  tracker
257
271
  end
258
272
 
259
- def self.rescan tracker, files
273
+ #Rescan a subset of files in a Rails application.
274
+ #
275
+ #A full scan must have been run already to use this method.
276
+ #The returned Tracker object from Brakeman.run is used as a starting point
277
+ #for the rescan.
278
+ #
279
+ #Options may be given as a hash with the same values as Brakeman.run.
280
+ #Note that these options will be merged into the Tracker.
281
+ #
282
+ #This method returns a RescanReport object with information about the scan.
283
+ #However, the Tracker object will also be modified as the scan is run.
284
+ def self.rescan tracker, files, options = {}
260
285
  require 'brakeman/rescanner'
261
286
 
287
+ tracker.options.merge! options
288
+
289
+ @quiet = !!tracker.options[:quiet]
290
+ @debug = !!tracker.options[:debug]
291
+
262
292
  Rescanner.new(tracker.options, tracker.processor, files).recheck
263
293
  end
294
+
295
+ def self.notify message
296
+ $stderr.puts message unless @quiet
297
+ end
298
+
299
+ def self.debug message
300
+ $stderr.puts message if @debug
301
+ end
264
302
  end
@@ -55,7 +55,7 @@ class Brakeman::CallIndex
55
55
  elsif method
56
56
  calls = calls_by_method method
57
57
  else
58
- warn "Invalid arguments to CallCache#find_calls: #{options.inspect}"
58
+ notify "Invalid arguments to CallCache#find_calls: #{options.inspect}"
59
59
  end
60
60
 
61
61
  return [] if calls.nil?
@@ -89,7 +89,7 @@ class Brakeman::Checks
89
89
  unless tracker.options[:skip_checks].include? check_name or
90
90
  (tracker.options[:run_checks] and not tracker.options[:run_checks].include? check_name)
91
91
 
92
- warn " - #{check_name}"
92
+ Brakeman.notify " - #{check_name}"
93
93
 
94
94
  check = c.new(tracker)
95
95
  check.run_check
@@ -120,7 +120,7 @@ class Brakeman::Checks
120
120
  unless tracker.options[:skip_checks].include? check_name or
121
121
  (tracker.options[:run_checks] and not tracker.options[:run_checks].include? check_name)
122
122
 
123
- warn " - #{check_name}"
123
+ Brakeman.notify " - #{check_name}"
124
124
 
125
125
  threads << Thread.new do
126
126
  begin
@@ -128,7 +128,7 @@ class Brakeman::Checks
128
128
  check.run_check
129
129
  check.warnings
130
130
  rescue Exception => e
131
- warn "[#{check_name}] #{e}"
131
+ Brakeman.notify "[#{check_name}] #{e}"
132
132
  []
133
133
  end
134
134
  end
@@ -141,7 +141,7 @@ class Brakeman::Checks
141
141
 
142
142
  threads.each { |t| t.join }
143
143
 
144
- warn "Checks finished, collecting results..."
144
+ Brakeman.notify "Checks finished, collecting results..."
145
145
 
146
146
  #Collect results
147
147
  threads.each do |thread|
@@ -20,7 +20,6 @@ class Brakeman::BaseCheck < SexpProcessor
20
20
  @tracker = tracker
21
21
  @string_interp = false
22
22
  @current_set = nil
23
- @debug_mode = tracker.options[:debug]
24
23
  @current_template = @current_module = @current_class = @current_method = nil
25
24
  self.strict = false
26
25
  self.auto_shift_type = false
@@ -397,8 +396,4 @@ class Brakeman::BaseCheck < SexpProcessor
397
396
  "config/environment.rb"
398
397
  end
399
398
  end
400
-
401
- def debug_info msg
402
- Kernel.warn msg if @debug_mode
403
- end
404
399
  end
@@ -44,9 +44,11 @@ class Brakeman::CheckCrossSiteScripting < Brakeman::BaseCheck
44
44
  @models = tracker.models.keys
45
45
  @inspect_arguments = tracker.options[:check_arguments]
46
46
 
47
- link_to_check = Brakeman::CheckLinkTo.new(tracker)
48
- link_to_check.run_check
49
- warnings.concat link_to_check.warnings unless link_to_check.warnings.empty?
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
50
52
 
51
53
  @known_dangerous = Set.new([:truncate, :concat])
52
54
 
@@ -59,10 +61,10 @@ class Brakeman::CheckCrossSiteScripting < Brakeman::BaseCheck
59
61
  tracker.each_template do |name, template|
60
62
  @current_template = template
61
63
  template[:outputs].each do |out|
62
- debug_info "Checking #{name} for direct XSS"
64
+ Brakeman.debug "Checking #{name} for direct XSS"
63
65
 
64
66
  unless check_for_immediate_xss out
65
- debug_info "Checking #{name} for indirect XSS"
67
+ Brakeman.debug "Checking #{name} for indirect XSS"
66
68
 
67
69
  @matched = false
68
70
  @mark = false
@@ -266,7 +268,14 @@ end
266
268
  #This _only_ checks calls to link_to
267
269
  class Brakeman::CheckLinkTo < Brakeman::CheckCrossSiteScripting
268
270
  def run_check
269
- @ignore_methods = []
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
+
270
279
  @known_dangerous = []
271
280
  #Ideally, I think this should also check to see if people are setting
272
281
  #:escape => false
@@ -15,7 +15,7 @@ class Brakeman::CheckDefaultRoutes < Brakeman::BaseCheck
15
15
  :confidence => CONFIDENCE[:high],
16
16
  :file => "#{tracker.options[:app_path]}/config/routes.rb"
17
17
  else #Report each controller separately
18
- debug_info "Checking each controller for default routes"
18
+ Brakeman.debug "Checking each controller for default routes"
19
19
 
20
20
  tracker.routes.each do |name, actions|
21
21
  if actions.is_a? Array and actions[0] == :allow_all_actions
@@ -7,10 +7,10 @@ class Brakeman::CheckEvaluation < Brakeman::BaseCheck
7
7
 
8
8
  #Process calls
9
9
  def run_check
10
- debug_info "Finding eval-like calls"
10
+ Brakeman.debug "Finding eval-like calls"
11
11
  calls = tracker.find_call :method => [:eval, :instance_eval, :class_eval, :module_eval]
12
12
 
13
- debug_info "Processing eval-like calls"
13
+ Brakeman.debug "Processing eval-like calls"
14
14
  calls.each do |call|
15
15
  process_result call
16
16
  end
@@ -13,13 +13,13 @@ class Brakeman::CheckExecute < Brakeman::BaseCheck
13
13
 
14
14
  #Check models, controllers, and views for command injection.
15
15
  def run_check
16
- debug_info "Finding system calls using ``"
16
+ Brakeman.debug "Finding system calls using ``"
17
17
  check_for_backticks tracker
18
18
 
19
- debug_info "Finding other system calls"
19
+ Brakeman.debug "Finding other system calls"
20
20
  calls = tracker.find_call :targets => [:IO, :Open3, :Kernel, nil], :methods => [:exec, :popen, :popen3, :syscall, :system]
21
21
 
22
- debug_info "Processing system calls"
22
+ Brakeman.debug "Processing system calls"
23
23
  calls.each do |result|
24
24
  process_result result
25
25
  end
@@ -6,16 +6,16 @@ class Brakeman::CheckFileAccess < Brakeman::BaseCheck
6
6
  Brakeman::Checks.add self
7
7
 
8
8
  def run_check
9
- debug_info "Finding possible file access"
9
+ Brakeman.debug "Finding possible file access"
10
10
  methods = tracker.find_call :targets => [:Dir, :File, :IO, :Kernel, :"Net::FTP", :"Net::HTTP", :PStore, :Pathname, :Shell, :YAML], :methods => [:[], :chdir, :chroot, :delete, :entries, :foreach, :glob, :install, :lchmod, :lchown, :link, :load, :load_file, :makedirs, :move, :new, :open, :read, :read_lines, :rename, :rmdir, :safe_unlink, :symlink, :syscopy, :sysopen, :truncate, :unlink]
11
11
 
12
- debug_info "Finding calls to load()"
12
+ Brakeman.debug "Finding calls to load()"
13
13
  methods.concat tracker.find_call :target => false, :method => :load
14
14
 
15
- debug_info "Finding calls using FileUtils"
15
+ Brakeman.debug "Finding calls using FileUtils"
16
16
  methods.concat tracker.find_call :target => :FileUtils
17
17
 
18
- debug_info "Processing found calls"
18
+ Brakeman.debug "Processing found calls"
19
19
  methods.each do |call|
20
20
  process_result call
21
21
  end
@@ -28,7 +28,7 @@ class Brakeman::CheckMailTo < Brakeman::BaseCheck
28
28
  #Check for javascript encoding of mail_to address
29
29
  # mail_to email, name, :encode => :javascript
30
30
  def mail_to_javascript?
31
- debug_info "Checking calls to mail_to for javascript encoding"
31
+ Brakeman.debug "Checking calls to mail_to for javascript encoding"
32
32
 
33
33
  tracker.find_call(:target => false, :method => :mail_to).each do |result|
34
34
  call = result[:call]
@@ -21,7 +21,7 @@ class Brakeman::CheckMassAssignment < Brakeman::BaseCheck
21
21
 
22
22
  @results = Set.new
23
23
 
24
- debug_info "Finding possible mass assignment calls on #{models.length} models"
24
+ Brakeman.debug "Finding possible mass assignment calls on #{models.length} models"
25
25
  calls = tracker.find_call :chained => true, :targets => models, :methods => [:new,
26
26
  :attributes=,
27
27
  :update_attribute,
@@ -30,7 +30,7 @@ class Brakeman::CheckMassAssignment < Brakeman::BaseCheck
30
30
  :create,
31
31
  :create!]
32
32
 
33
- debug_info "Processing possible mass assignment calls"
33
+ Brakeman.debug "Processing possible mass assignment calls"
34
34
  calls.each do |result|
35
35
  process_result result
36
36
  end
@@ -29,7 +29,7 @@ class Brakeman::CheckQuoteTableName < Brakeman::BaseCheck
29
29
  end
30
30
 
31
31
  def uses_quote_table_name?
32
- debug_info "Finding calls to quote_table_name()"
32
+ Brakeman.debug "Finding calls to quote_table_name()"
33
33
 
34
34
  not tracker.find_call(:target => false, :method => :quote_table_name).empty?
35
35
  end
@@ -9,7 +9,7 @@ class Brakeman::CheckRedirect < Brakeman::BaseCheck
9
9
  Brakeman::Checks.add self
10
10
 
11
11
  def run_check
12
- debug_info "Finding calls to redirect_to()"
12
+ Brakeman.debug "Finding calls to redirect_to()"
13
13
 
14
14
  @tracker.find_call(:target => false, :method => :redirect_to).each do |res|
15
15
  process_result res
@@ -42,7 +42,7 @@ class Brakeman::CheckRedirect < Brakeman::BaseCheck
42
42
  #which can be used to enable/disable reporting output of method calls which use
43
43
  #user input as arguments.
44
44
  def include_user_input? call
45
- debug_info "Checking if call includes user input"
45
+ Brakeman.debug "Checking if call includes user input"
46
46
 
47
47
  if tracker.options[:ignore_redirect_to_model] and call? call[3][1] and
48
48
  call[3][1][2] == :new and call[3][1][1]
@@ -6,7 +6,7 @@ class Brakeman::CheckSendFile < Brakeman::CheckFileAccess
6
6
  Brakeman::Checks.add self
7
7
 
8
8
  def run_check
9
- debug_info "Finding all calls to send_file()"
9
+ Brakeman.debug "Finding all calls to send_file()"
10
10
 
11
11
  methods = tracker.find_call :target => false, :method => :send_file
12
12
 
@@ -14,7 +14,7 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
14
14
  def run_check
15
15
  @rails_version = tracker.config[:rails_version]
16
16
 
17
- debug_info "Finding possible SQL calls on models"
17
+ Brakeman.debug "Finding possible SQL calls on models"
18
18
  if tracker.options[:rails3]
19
19
  calls = tracker.find_call :targets => tracker.models.keys,
20
20
  :methods => /^(find.*|first|last|all|where|order|group|having)$/,
@@ -25,16 +25,16 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
25
25
  :chained => true
26
26
  end
27
27
 
28
- debug_info "Finding possible SQL calls with no target"
28
+ Brakeman.debug "Finding possible SQL calls with no target"
29
29
  calls.concat tracker.find_call(:target => nil, :method => /^(find.*|last|first|all|count|sum|average|minumum|maximum|count_by_sql)$/)
30
30
 
31
- debug_info "Finding possible SQL calls using constantized()"
31
+ Brakeman.debug "Finding possible SQL calls using constantized()"
32
32
  calls.concat tracker.find_call(:method => /^(find.*|last|first|all|count|sum|average|minumum|maximum|count_by_sql)$/).select { |result| constantize_call? result }
33
33
 
34
- debug_info "Finding calls to named_scope or scope"
34
+ Brakeman.debug "Finding calls to named_scope or scope"
35
35
  calls.concat find_scope_calls
36
36
 
37
- debug_info "Processing possible SQL calls"
37
+ Brakeman.debug "Processing possible SQL calls"
38
38
  calls.each do |c|
39
39
  process_result c
40
40
  end
@@ -23,7 +23,7 @@ class Brakeman::CheckStripTags < Brakeman::BaseCheck
23
23
  end
24
24
 
25
25
  def uses_strip_tags?
26
- debug_info "Finding calls to strip_tags()"
26
+ Brakeman.debug "Finding calls to strip_tags()"
27
27
 
28
28
  not tracker.find_call(:target => false, :method => :strip_tags).empty?
29
29
  end
@@ -6,7 +6,7 @@ class Brakeman::CheckTranslateBug < Brakeman::BaseCheck
6
6
  Brakeman::Checks.add self
7
7
 
8
8
  def run_check
9
- if (version_between?('2.3.0', '2.3.99') and tracker.options[:escape_html]) or
9
+ if (version_between?('2.3.0', '2.3.99') and tracker.config[:escape_html]) or
10
10
  version_between?('3.0.0', '3.0.10') or
11
11
  version_between?('3.1.0', '3.1.1')
12
12
 
@@ -34,7 +34,7 @@ class Brakeman::CheckTranslateBug < Brakeman::BaseCheck
34
34
  end
35
35
 
36
36
  def uses_translate?
37
- debug_info "Finding calls to translate() or t()"
37
+ Brakeman.debug "Finding calls to translate() or t()"
38
38
 
39
39
  not tracker.find_call(:target => nil, :methods => [:t, :translate]).empty?
40
40
  end
@@ -23,7 +23,7 @@ class Brakeman::CheckWithoutProtection < Brakeman::BaseCheck
23
23
 
24
24
  @results = Set.new
25
25
 
26
- debug_info "Finding all mass assignments"
26
+ Brakeman.debug "Finding all mass assignments"
27
27
  calls = tracker.find_call :targets => models, :methods => [:new,
28
28
  :attributes=,
29
29
  :update_attribute,
@@ -32,7 +32,7 @@ class Brakeman::CheckWithoutProtection < Brakeman::BaseCheck
32
32
  :create,
33
33
  :create!]
34
34
 
35
- debug_info "Processing all mass assignments"
35
+ Brakeman.debug "Processing all mass assignments"
36
36
  calls.each do |result|
37
37
  process_result result
38
38
  end
@@ -87,7 +87,7 @@ class Brakeman::ControllerAliasProcessor < Brakeman::AliasProcessor
87
87
  method = find_method name, @current_class
88
88
 
89
89
  if method.nil?
90
- warn "[Notice] Could not find filter #{name}" if @tracker.options[:debug]
90
+ Brakeman.debug "[Notice] Could not find filter #{name}"
91
91
  return
92
92
  end
93
93
 
@@ -207,7 +207,7 @@ class Brakeman::ControllerAliasProcessor < Brakeman::AliasProcessor
207
207
  when :lit, :str
208
208
  filter[option] = value[1]
209
209
  else
210
- warn "[Notice] Unknown before_filter value: #{option} => #{value}" if @tracker.options[:debug]
210
+ Brakeman.debug "[Notice] Unknown before_filter value: #{option} => #{value}"
211
211
  end
212
212
  else
213
213
  filter[:all] = true
@@ -22,7 +22,7 @@ class Brakeman::ControllerProcessor < Brakeman::BaseProcessor
22
22
  #s(:class, NAME, PARENT, s(:scope ...))
23
23
  def process_class exp
24
24
  if @controller
25
- warn "[Notice] Skipping inner class: #{class_name exp[1]}" if @tracker.options[:debug]
25
+ Brakeman.debug "[Notice] Skipping inner class: #{class_name exp[1]}"
26
26
  return ignore
27
27
  end
28
28
 
@@ -83,7 +83,7 @@ class Brakeman::ControllerProcessor < Brakeman::BaseProcessor
83
83
  unless Dir.glob("#{@tracker.options[:app_path]}/app/views/layouts/#{name}.html.{erb,haml}").empty?
84
84
  @controller[:layout] = "layouts/#{name}"
85
85
  else
86
- warn "[Notice] Layout not found: #{name}" if @tracker.options[:debug]
86
+ Brakeman.debug "[Notice] Layout not found: #{name}"
87
87
  end
88
88
  elsif sexp? args[-1] and (args[-1][0] == :nil or args[-1][0] == :false)
89
89
  #layout :false or layout nil
@@ -37,7 +37,7 @@ class Brakeman::Rails2ConfigProcessor < Brakeman::BaseProcessor
37
37
  target = process target if sexp? target
38
38
 
39
39
  if exp[2] == :gem and exp[3][1][1] == "erubis"
40
- warn "[Notice] Using Erubis for ERB templates"
40
+ Brakeman.notify "[Notice] Using Erubis for ERB templates"
41
41
  @tracker.config[:erubis] = true
42
42
  end
43
43
 
@@ -21,10 +21,13 @@ module Brakeman::RenderHelper
21
21
 
22
22
  #Processes layout
23
23
  def process_layout name = nil
24
- layout = name || layout_name
25
- return unless layout
24
+ if name.nil? and defined? layout_name
25
+ name = layout_name
26
+ end
27
+
28
+ return unless name
26
29
 
27
- process_template layout, nil
30
+ process_template name, nil
28
31
  end
29
32
 
30
33
  #Determines file name for partial and then processes it
@@ -50,7 +53,7 @@ module Brakeman::RenderHelper
50
53
  name = name.to_s.gsub(/^\//, "")
51
54
  template = @tracker.templates[name.to_sym]
52
55
  unless template
53
- warn "[Notice] No such template: #{name}" if @tracker.options[:debug]
56
+ Brakeman.debug "[Notice] No such template: #{name}"
54
57
  return
55
58
  end
56
59
 
@@ -19,7 +19,7 @@ class Brakeman::ModelProcessor < Brakeman::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 @tracker.options[:debug]
22
+ Brakeman.debug "[Notice] Skipping inner class: #{class_name exp[1]}"
23
23
  ignore
24
24
  else
25
25
  @model = { :name => class_name(exp[1]),
@@ -56,6 +56,8 @@ class Brakeman::ModelProcessor < Brakeman::BaseProcessor
56
56
  case method
57
57
  when :private, :protected, :public
58
58
  @visibility = method
59
+ when :attr_accessible
60
+ @model[:attr_accessible] ||= []
59
61
  else
60
62
  #??
61
63
  end
@@ -19,7 +19,7 @@ class Brakeman::OutputProcessor < Ruby2Ruby
19
19
  begin
20
20
  super exp if sexp? exp and not exp.empty?
21
21
  rescue Exception => e
22
- warn "While formatting #{exp}: #{e}\n#{e.backtrace.join("\n")}" if @tracker.options[:debug]
22
+ Brakeman.debug "While formatting #{exp}: #{e}\n#{e.backtrace.join("\n")}"
23
23
  end
24
24
  end
25
25
 
@@ -83,7 +83,7 @@ class Brakeman::Report
83
83
 
84
84
 
85
85
  tracker.errors.each do |w|
86
- p w if tracker.options[:debug]
86
+ Brakeman.debug w.inspect
87
87
 
88
88
  if html
89
89
  w[:error] = CGI.escapeHTML w[:error]
@@ -45,7 +45,7 @@ class Brakeman::Rescanner < Brakeman::Scanner
45
45
 
46
46
  SCAN_ORDER.each do |type|
47
47
  paths_by_type[type].each do |path|
48
- warn "Rescanning #{path} as #{type}" if tracker.options[:debug]
48
+ Brakeman.debug "Rescanning #{path} as #{type}"
49
49
 
50
50
  if rescan_file path, type
51
51
  @changes = true
@@ -244,4 +244,12 @@ class Brakeman::RescanReport
244
244
  def diff
245
245
  @diff ||= @new_results.diff(@old_results)
246
246
  end
247
+
248
+ def to_s
249
+ <<-OUTPUT
250
+ Total warnings: #{all_warnings.length}
251
+ Fixed warnings: #{fixed_warnings.length}
252
+ New warnings: #{new_warnings.length}
253
+ OUTPUT
254
+ end
247
255
  end
@@ -51,23 +51,23 @@ class Brakeman::Scanner
51
51
 
52
52
  #Process everything in the Rails application
53
53
  def process
54
- warn "Processing configuration..."
54
+ Brakeman.notify "Processing configuration..."
55
55
  process_config
56
- warn "Processing gems..."
56
+ Brakeman.notify "Processing gems..."
57
57
  process_gems
58
- warn "Processing initializers..."
58
+ Brakeman.notify "Processing initializers..."
59
59
  process_initializers
60
- warn "Processing libs..."
60
+ Brakeman.notify "Processing libs..."
61
61
  process_libs
62
- warn "Processing routes... "
62
+ Brakeman.notify "Processing routes... "
63
63
  process_routes
64
- warn "Processing templates... "
64
+ Brakeman.notify "Processing templates... "
65
65
  process_templates
66
- warn "Processing models... "
66
+ Brakeman.notify "Processing models... "
67
67
  process_models
68
- warn "Processing controllers... "
68
+ Brakeman.notify "Processing controllers... "
69
69
  process_controllers
70
- warn "Indexing call sites... "
70
+ Brakeman.notify "Indexing call sites... "
71
71
  index_call_sites
72
72
  tracker
73
73
  end
@@ -89,7 +89,7 @@ class Brakeman::Scanner
89
89
  (File.exists? "#@path/Gemfile" and File.read("#@path/Gemfile").include? "rails_xss")
90
90
 
91
91
  tracker.config[:escape_html] = true
92
- warn "[Notice] Escaping HTML by default"
92
+ Brakeman.notify "[Notice] Escaping HTML by default"
93
93
  end
94
94
  end
95
95
 
@@ -99,7 +99,7 @@ class Brakeman::Scanner
99
99
  end
100
100
 
101
101
  rescue Exception => e
102
- warn "[Notice] Error while processing config/#{file}"
102
+ Brakeman.notify "[Notice] Error while processing config/#{file}"
103
103
  tracker.error e.exception(e.message + "\nwhile processing Gemfile"), e.backtrace
104
104
  end
105
105
 
@@ -115,7 +115,7 @@ class Brakeman::Scanner
115
115
  end
116
116
  end
117
117
  rescue Exception => e
118
- warn "[Notice] Error while processing Gemfile."
118
+ Brakeman.notify "[Notice] Error while processing Gemfile."
119
119
  tracker.error e.exception(e.message + "\nWhile processing Gemfile"), e.backtrace
120
120
  end
121
121
 
@@ -144,7 +144,7 @@ class Brakeman::Scanner
144
144
  #Adds parsed information to tracker.libs.
145
145
  def process_libs
146
146
  if options[:skip_libs]
147
- warn '[Skipping]'
147
+ Brakeman.notify '[Skipping]'
148
148
  return
149
149
  end
150
150
 
@@ -153,7 +153,7 @@ class Brakeman::Scanner
153
153
  current = 0
154
154
 
155
155
  lib_files.each do |f|
156
- warn "Processing #{f}" if options[:debug]
156
+ Brakeman.debug "Processing #{f}"
157
157
  if @report_progress
158
158
  $stderr.print " #{current}/#{total} files processed\r"
159
159
  current += 1
@@ -183,11 +183,11 @@ class Brakeman::Scanner
183
183
  @processor.process_routes parse_ruby(File.read("#@path/config/routes.rb"))
184
184
  rescue Exception => e
185
185
  tracker.error e.exception(e.message + "\nWhile processing routes.rb"), e.backtrace
186
- warn "[Notice] Error while processing routes - assuming all public controller methods are actions."
186
+ Brakeman.notify "[Notice] Error while processing routes - assuming all public controller methods are actions."
187
187
  options[:assume_all_routes] = true
188
188
  end
189
189
  else
190
- warn "[Notice] No route information found"
190
+ Brakeman.notify "[Notice] No route information found"
191
191
  end
192
192
  end
193
193
 
@@ -200,7 +200,7 @@ class Brakeman::Scanner
200
200
  current = 0
201
201
 
202
202
  controller_files.each do |f|
203
- warn "Processing #{f}" if options[:debug]
203
+ Brakeman.debug "Processing #{f}"
204
204
  if @report_progress
205
205
  $stderr.print " #{current}/#{total} files processed\r"
206
206
  current += 1
@@ -212,7 +212,7 @@ class Brakeman::Scanner
212
212
  current = 0
213
213
  total = tracker.controllers.length
214
214
 
215
- warn "Processing data flow in controllers..."
215
+ Brakeman.notify "Processing data flow in controllers..."
216
216
 
217
217
  tracker.controllers.each do |name, controller|
218
218
  if @report_progress
@@ -258,7 +258,7 @@ class Brakeman::Scanner
258
258
  total = tracker.templates.length
259
259
  count = 0
260
260
 
261
- warn "Processing data flow in templates..."
261
+ Brakeman.notify "Processing data flow in templates..."
262
262
 
263
263
  tracker.templates.keys.dup.each do |name|
264
264
  if @report_progress
@@ -1,3 +1,3 @@
1
1
  module Brakeman
2
- Version = "1.2.0"
2
+ Version = "1.2.1"
3
3
  end
@@ -5,6 +5,8 @@ class Brakeman::Warning
5
5
 
6
6
  attr_accessor :code, :context, :file, :message
7
7
 
8
+ TEXT_CONFIDENCE = [ "High", "Medium", "Weak" ]
9
+
8
10
  #+options[:result]+ can be a result from Tracker#find_call. Otherwise, it can be +nil+.
9
11
  def initialize options = {}
10
12
  @view_name = nil
@@ -111,4 +113,13 @@ class Brakeman::Warning
111
113
 
112
114
  @row
113
115
  end
116
+
117
+ def to_s
118
+ output = "(#{TEXT_CONFIDENCE[self.confidence]}) #{self.warning_type} - #{self.message}"
119
+ output << " near line #{self.line}" if self.line
120
+ output << " in #{self.file}" if self.file
121
+ output << ": #{self.format_code}" if self.code
122
+
123
+ output
124
+ end
114
125
  end
metadata CHANGED
@@ -1,127 +1,101 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: brakeman
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 1
7
- - 2
8
- - 0
9
- version: 1.2.0
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.2.1
5
+ prerelease:
10
6
  platform: ruby
11
- authors:
7
+ authors:
12
8
  - Justin Collins
13
9
  autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
-
17
- date: 2012-01-13 00:00:00 -08:00
18
- default_executable:
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
12
+ date: 2012-01-20 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
21
15
  name: activesupport
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: &76221240 !ruby/object:Gem::Requirement
24
17
  none: false
25
- requirements:
26
- - - ">="
27
- - !ruby/object:Gem::Version
28
- segments:
29
- - 0
30
- version: "0"
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
31
22
  type: :runtime
32
- version_requirements: *id001
33
- - !ruby/object:Gem::Dependency
34
- name: i18n
35
23
  prerelease: false
36
- requirement: &id002 !ruby/object:Gem::Requirement
24
+ version_requirements: *76221240
25
+ - !ruby/object:Gem::Dependency
26
+ name: i18n
27
+ requirement: &76220920 !ruby/object:Gem::Requirement
37
28
  none: false
38
- requirements:
39
- - - ">="
40
- - !ruby/object:Gem::Version
41
- segments:
42
- - 0
43
- version: "0"
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
44
33
  type: :runtime
45
- version_requirements: *id002
46
- - !ruby/object:Gem::Dependency
47
- name: ruby2ruby
48
34
  prerelease: false
49
- requirement: &id003 !ruby/object:Gem::Requirement
35
+ version_requirements: *76220920
36
+ - !ruby/object:Gem::Dependency
37
+ name: ruby2ruby
38
+ requirement: &76220320 !ruby/object:Gem::Requirement
50
39
  none: false
51
- requirements:
40
+ requirements:
52
41
  - - ~>
53
- - !ruby/object:Gem::Version
54
- segments:
55
- - 1
56
- - 2
57
- version: "1.2"
42
+ - !ruby/object:Gem::Version
43
+ version: '1.2'
58
44
  type: :runtime
59
- version_requirements: *id003
60
- - !ruby/object:Gem::Dependency
61
- name: ruport
62
45
  prerelease: false
63
- requirement: &id004 !ruby/object:Gem::Requirement
46
+ version_requirements: *76220320
47
+ - !ruby/object:Gem::Dependency
48
+ name: ruport
49
+ requirement: &76219720 !ruby/object:Gem::Requirement
64
50
  none: false
65
- requirements:
51
+ requirements:
66
52
  - - ~>
67
- - !ruby/object:Gem::Version
68
- segments:
69
- - 1
70
- - 6
71
- version: "1.6"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.6'
72
55
  type: :runtime
73
- version_requirements: *id004
74
- - !ruby/object:Gem::Dependency
75
- name: erubis
76
56
  prerelease: false
77
- requirement: &id005 !ruby/object:Gem::Requirement
57
+ version_requirements: *76219720
58
+ - !ruby/object:Gem::Dependency
59
+ name: erubis
60
+ requirement: &76943790 !ruby/object:Gem::Requirement
78
61
  none: false
79
- requirements:
62
+ requirements:
80
63
  - - ~>
81
- - !ruby/object:Gem::Version
82
- segments:
83
- - 2
84
- - 6
85
- version: "2.6"
64
+ - !ruby/object:Gem::Version
65
+ version: '2.6'
86
66
  type: :runtime
87
- version_requirements: *id005
88
- - !ruby/object:Gem::Dependency
89
- name: haml
90
67
  prerelease: false
91
- requirement: &id006 !ruby/object:Gem::Requirement
68
+ version_requirements: *76943790
69
+ - !ruby/object:Gem::Dependency
70
+ name: haml
71
+ requirement: &76943560 !ruby/object:Gem::Requirement
92
72
  none: false
93
- requirements:
73
+ requirements:
94
74
  - - ~>
95
- - !ruby/object:Gem::Version
96
- segments:
97
- - 3
98
- - 0
99
- version: "3.0"
75
+ - !ruby/object:Gem::Version
76
+ version: '3.0'
100
77
  type: :runtime
101
- version_requirements: *id006
102
- - !ruby/object:Gem::Dependency
103
- name: sass
104
78
  prerelease: false
105
- requirement: &id007 !ruby/object:Gem::Requirement
79
+ version_requirements: *76943560
80
+ - !ruby/object:Gem::Dependency
81
+ name: sass
82
+ requirement: &76943330 !ruby/object:Gem::Requirement
106
83
  none: false
107
- requirements:
84
+ requirements:
108
85
  - - ~>
109
- - !ruby/object:Gem::Version
110
- segments:
111
- - 3
112
- - 0
113
- version: "3.0"
86
+ - !ruby/object:Gem::Version
87
+ version: '3.0'
114
88
  type: :runtime
115
- version_requirements: *id007
116
- description: Brakeman detects security vulnerabilities in Ruby on Rails applications via static analysis.
89
+ prerelease: false
90
+ version_requirements: *76943330
91
+ description: Brakeman detects security vulnerabilities in Ruby on Rails applications
92
+ via static analysis.
117
93
  email:
118
- executables:
94
+ executables:
119
95
  - brakeman
120
96
  extensions: []
121
-
122
97
  extra_rdoc_files: []
123
-
124
- files:
98
+ files:
125
99
  - bin/brakeman
126
100
  - WARNING_TYPES
127
101
  - FEATURES
@@ -194,37 +168,28 @@ files:
194
168
  - lib/brakeman/processor.rb
195
169
  - lib/brakeman.rb
196
170
  - lib/brakeman/format/style.css
197
- has_rdoc: true
198
171
  homepage: http://brakemanscanner.org
199
172
  licenses: []
200
-
201
173
  post_install_message:
202
174
  rdoc_options: []
203
-
204
- require_paths:
175
+ require_paths:
205
176
  - lib
206
- required_ruby_version: !ruby/object:Gem::Requirement
177
+ required_ruby_version: !ruby/object:Gem::Requirement
207
178
  none: false
208
- requirements:
209
- - - ">="
210
- - !ruby/object:Gem::Version
211
- segments:
212
- - 0
213
- version: "0"
214
- required_rubygems_version: !ruby/object:Gem::Requirement
179
+ requirements:
180
+ - - ! '>='
181
+ - !ruby/object:Gem::Version
182
+ version: '0'
183
+ required_rubygems_version: !ruby/object:Gem::Requirement
215
184
  none: false
216
- requirements:
217
- - - ">="
218
- - !ruby/object:Gem::Version
219
- segments:
220
- - 0
221
- version: "0"
185
+ requirements:
186
+ - - ! '>='
187
+ - !ruby/object:Gem::Version
188
+ version: '0'
222
189
  requirements: []
223
-
224
190
  rubyforge_project:
225
- rubygems_version: 1.3.7
191
+ rubygems_version: 1.8.10
226
192
  signing_key:
227
193
  specification_version: 3
228
194
  summary: Security vulnerability scanner for Ruby on Rails.
229
195
  test_files: []
230
-