brakeman 2.6.1 → 2.6.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +15 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/CHANGES +14 -0
  5. data/bin/brakeman +3 -3
  6. data/lib/brakeman.rb +17 -4
  7. data/lib/brakeman/app_tree.rb +1 -1
  8. data/lib/brakeman/checks.rb +8 -1
  9. data/lib/brakeman/checks/base_check.rb +1 -2
  10. data/lib/brakeman/checks/check_create_with.rb +75 -0
  11. data/lib/brakeman/checks/check_default_routes.rb +3 -3
  12. data/lib/brakeman/checks/check_i18n_xss.rb +1 -1
  13. data/lib/brakeman/checks/check_json_parsing.rb +1 -1
  14. data/lib/brakeman/checks/check_redirect.rb +0 -1
  15. data/lib/brakeman/checks/check_send.rb +17 -4
  16. data/lib/brakeman/checks/check_session_settings.rb +14 -11
  17. data/lib/brakeman/checks/check_sql.rb +22 -13
  18. data/lib/brakeman/checks/check_sql_cves.rb +1 -1
  19. data/lib/brakeman/checks/check_symbol_dos.rb +10 -1
  20. data/lib/brakeman/options.rb +11 -1
  21. data/lib/brakeman/parsers/rails3_erubis.rb +0 -8
  22. data/lib/brakeman/parsers/template_parser.rb +1 -1
  23. data/lib/brakeman/processors/gem_processor.rb +9 -3
  24. data/lib/brakeman/processors/output_processor.rb +0 -7
  25. data/lib/brakeman/report/report_base.rb +10 -3
  26. data/lib/brakeman/report/report_csv.rb +1 -1
  27. data/lib/brakeman/report/report_hash.rb +1 -0
  28. data/lib/brakeman/report/report_json.rb +1 -2
  29. data/lib/brakeman/report/report_markdown.rb +1 -1
  30. data/lib/brakeman/report/report_table.rb +1 -1
  31. data/lib/brakeman/report/templates/header.html.erb +1 -1
  32. data/lib/brakeman/scanner.rb +16 -9
  33. data/lib/brakeman/tracker.rb +5 -1
  34. data/lib/brakeman/util.rb +3 -3
  35. data/lib/brakeman/version.rb +1 -1
  36. data/lib/brakeman/warning_codes.rb +2 -0
  37. data/lib/ruby_parser/bm_sexp.rb +8 -1
  38. metadata +78 -43
  39. metadata.gz.sig +0 -0
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NTdlNDlhNGRkMDhlNWQ5NGNlYWZlOWI2NTI5ZWI4NjBlZGU4YzBmNg==
5
+ data.tar.gz: !binary |-
6
+ YTliNDliZjhkYmZjNzNkNmY0M2QxY2UxOGNiMGQ3NTQ1YWVkMjg5ZA==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ NmU3Yzc2NmQxYTM2NzZlZDA2YWZmYjExYTczOTZkYjdiMmI2ZDFiN2FjNDUy
10
+ NjVmMjYyODk0ZmRhNmIxNzEzNTZmNjE1MmFjNjE2ZTA5N2VkZjEwNDA3OTQ3
11
+ OGE1YWQ4MjE5MzFhMzIxZGVjNjMyODc3NDgxY2IxYzhhOWRkMTM=
12
+ data.tar.gz: !binary |-
13
+ YjgwZmI1N2NiOGIxNGJiODgyZTU2NjJhZDRlN2QzOWZhN2JhZDU1NTE1ZGY2
14
+ ZTE2MDY1MDU3M2MzY2M0MzM1MTM5NWM4NmM3YjZiZDQzNjg4OGUyYTVlYjM3
15
+ N2E2MjI1MGViNjY3MjkwYzZiYWUyODYwZGYyMzljODkzZjExMmE=
checksums.yaml.gz.sig ADDED
Binary file
data.tar.gz.sig CHANGED
Binary file
data/CHANGES CHANGED
@@ -1,3 +1,17 @@
1
+ # 2.6.2
2
+
3
+ * Add check for CVE-2014-3415
4
+ * Avoid warning about symbolizing safe parameters
5
+ * Update ruby2ruby dependency to 2.1.1
6
+ * Expand app path in one place instead of all over (Jeff Rafter)
7
+ * Add `--add-checks-path` option for external checks (Clint Gibler)
8
+ * Fix SQL injection detection in deep nested string building
9
+ * Add `-4` option to force Rails 4 mode
10
+ * Check entire call for `send`
11
+ * Check for .gitignore of secrets in subdirectories
12
+ * Fix block statment endings in Erubis
13
+ * Fix undefined variable in controller processing error (Jason Barnabe)
14
+
1
15
  # 2.6.1
2
16
 
3
17
  * Add check for CVE-2014-3482 and CVE-2014-3483
data/bin/brakeman CHANGED
@@ -17,7 +17,7 @@ end
17
17
 
18
18
  #Exit early for these options
19
19
  if options[:list_checks]
20
- Brakeman.list_checks
20
+ Brakeman.list_checks options
21
21
  exit
22
22
  elsif options[:create_config]
23
23
  Brakeman.dump_config options
@@ -36,9 +36,9 @@ end
36
36
  #Set application path according to the commandline arguments
37
37
  unless options[:app_path]
38
38
  if ARGV[-1].nil?
39
- options[:app_path] = File.expand_path "."
39
+ options[:app_path] = "."
40
40
  else
41
- options[:app_path] = File.expand_path ARGV[-1]
41
+ options[:app_path] = ARGV[-1]
42
42
  end
43
43
  end
44
44
 
data/lib/brakeman.rb CHANGED
@@ -76,7 +76,6 @@ module Brakeman
76
76
  options[:quiet] = true
77
77
  end
78
78
 
79
- options[:app_path] = File.expand_path(options[:app_path])
80
79
  options[:output_formats] = get_output_formats options
81
80
  options[:github_url] = get_github_url options
82
81
 
@@ -215,8 +214,11 @@ module Brakeman
215
214
  private_class_method :get_github_url
216
215
 
217
216
  #Output list of checks (for `-k` option)
218
- def self.list_checks
217
+ def self.list_checks options
219
218
  require 'brakeman/scanner'
219
+
220
+ add_external_checks options
221
+
220
222
  format_length = 30
221
223
 
222
224
  $stderr.puts "Available Checks:"
@@ -301,11 +303,14 @@ module Brakeman
301
303
  raise NoBrakemanError, "Cannot find lib/ directory."
302
304
  end
303
305
 
306
+ add_external_checks options
307
+
304
308
  #Start scanning
305
309
  scanner = Scanner.new options
310
+ tracker = scanner.tracker
306
311
 
307
- notify "Processing application in #{options[:app_path]}"
308
- tracker = scanner.process
312
+ notify "Processing application in #{tracker.app_path}"
313
+ scanner.process
309
314
 
310
315
  if options[:parallel_checks]
311
316
  notify "Running checks in parallel..."
@@ -383,6 +388,8 @@ module Brakeman
383
388
  require 'brakeman/differ'
384
389
  raise ArgumentError.new("Comparison file doesn't exist") unless File.exists? options[:previous_results_json]
385
390
 
391
+ add_external_checks options
392
+
386
393
  begin
387
394
  previous_results = MultiJson.load(File.read(options[:previous_results_json]), :symbolize_keys => true)[:warnings]
388
395
  rescue MultiJson::DecodeError
@@ -437,6 +444,12 @@ module Brakeman
437
444
  tracker.ignored_filter = config
438
445
  end
439
446
 
447
+ def self.add_external_checks options
448
+ options[:additional_checks_path].each do |path|
449
+ Brakeman::Checks.initialize_checks path
450
+ end if options[:additional_checks_path]
451
+ end
452
+
440
453
  class DependencyError < RuntimeError; end
441
454
  class RakeInstallError < RuntimeError; end
442
455
  class NoBrakemanError < RuntimeError; end
@@ -5,7 +5,7 @@ module Brakeman
5
5
  attr_reader :root
6
6
 
7
7
  def self.from_options(options)
8
- root = options[:app_path]
8
+ root = File.expand_path options[:app_path]
9
9
 
10
10
  # Convert files into Regexp for matching
11
11
  init_options = {}
@@ -13,13 +13,20 @@ class Brakeman::Checks
13
13
 
14
14
  #Add a check. This will call +_klass_.new+ when running tests
15
15
  def self.add klass
16
- @checks << klass
16
+ @checks << klass unless @checks.include? klass
17
17
  end
18
18
 
19
19
  def self.checks
20
20
  @checks
21
21
  end
22
22
 
23
+ def self.initialize_checks check_directory = ""
24
+ #Load all files in check_directory
25
+ Dir.glob(File.join(check_directory, "*.rb")).sort.each do |f|
26
+ require f
27
+ end
28
+ end
29
+
23
30
  #No need to use this directly.
24
31
  def initialize options = { }
25
32
  if options[:min_confidence]
@@ -177,7 +177,7 @@ class Brakeman::BaseCheck < Brakeman::SexpProcessor
177
177
  tracker.config[:rails][:active_record][:whitelist_attributes] == Sexp.new(:true)
178
178
 
179
179
  @mass_assign_disabled = true
180
- elsif version_between?("4.0.0", "4.9.9") && (!tracker.config[:gems][:protected_attributes] || (tracker.config[:rails][:active_record] &&
180
+ elsif tracker.options[:rails4] && (!tracker.config[:gems][:protected_attributes] || (tracker.config[:rails][:active_record] &&
181
181
  tracker.config[:rails][:active_record][:whitelist_attributes] == Sexp.new(:true)))
182
182
 
183
183
  @mass_assign_disabled = true
@@ -481,7 +481,6 @@ class Brakeman::BaseCheck < Brakeman::SexpProcessor
481
481
  end
482
482
 
483
483
  def lts_version? version
484
- tracker.config[:gems] and
485
484
  tracker.config[:gems][:'railslts-version'] and
486
485
  version_between? version, "2.3.18.99", tracker.config[:gems][:'railslts-version']
487
486
  end
@@ -0,0 +1,75 @@
1
+ require 'brakeman/checks/base_check'
2
+
3
+ class Brakeman::CheckCreateWith < Brakeman::BaseCheck
4
+ Brakeman::Checks.add self
5
+
6
+ @description = "Checks for strong params bypass in CVE-2014-3514"
7
+
8
+ def run_check
9
+ @warned = false
10
+
11
+ if version_between? "4.0.0", "4.0.8"
12
+ suggested_version = "4.0.9"
13
+ elsif version_between? "4.1.0", "4.1.4"
14
+ suggested_version = "4.1.5"
15
+ else
16
+ return
17
+ end
18
+
19
+ @message = "create_with is vulnerable to strong params bypass. Upgrade to Rails #{suggested_version} or patch"
20
+
21
+ tracker.find_call(:method => :create_with, :nested => true).each do |result|
22
+ process_result result
23
+ end
24
+
25
+ generic_warning unless @warned
26
+ end
27
+
28
+ def process_result result
29
+ return if duplicate? result
30
+ add_result result
31
+ arg = result[:call].first_arg
32
+
33
+ confidence = danger_level arg
34
+
35
+ if confidence
36
+ @warned = true
37
+
38
+ warn :warning_type => "Mass Assignment",
39
+ :warning_code => :CVE_2014_3514_call,
40
+ :result => result,
41
+ :message => @message,
42
+ :confidence => confidence,
43
+ :link_path => "https://groups.google.com/d/msg/rubyonrails-security/M4chq5Sb540/CC1Fh0Y_NWwJ"
44
+ end
45
+ end
46
+
47
+ #For a given create_with call, set confidence level.
48
+ #Ignore calls that use permit()
49
+ def danger_level exp
50
+ return unless sexp? exp
51
+
52
+ if call? exp and exp.method == :permit
53
+ nil
54
+ elsif request_value? exp
55
+ CONFIDENCE[:high]
56
+ elsif hash? exp
57
+ nil
58
+ elsif has_immediate_user_input?(exp)
59
+ CONFIDENCE[:high]
60
+ elsif include_user_input? exp
61
+ CONFIDENCE[:med]
62
+ else
63
+ CONFIDENCE[:low]
64
+ end
65
+ end
66
+
67
+ def generic_warning
68
+ warn :warning_type => "Mass Assignment",
69
+ :warning_code => :CVE_2014_3514,
70
+ :message => @message,
71
+ :file => gemfile_or_environment,
72
+ :confidence => CONFIDENCE[:med],
73
+ :link_path => "https://groups.google.com/d/msg/rubyonrails-security/M4chq5Sb540/CC1Fh0Y_NWwJ"
74
+ end
75
+ end
@@ -22,7 +22,7 @@ class Brakeman::CheckDefaultRoutes < Brakeman::BaseCheck
22
22
  :message => "All public methods in controllers are available as actions in routes.rb",
23
23
  :line => tracker.routes[:allow_all_actions].line,
24
24
  :confidence => CONFIDENCE[:high],
25
- :file => "#{tracker.options[:app_path]}/config/routes.rb"
25
+ :file => "#{tracker.app_path}/config/routes.rb"
26
26
  end
27
27
  end
28
28
 
@@ -44,7 +44,7 @@ class Brakeman::CheckDefaultRoutes < Brakeman::BaseCheck
44
44
  :message => "Any public method in #{name} can be used as an action for #{verb} requests.",
45
45
  :line => actions[2],
46
46
  :confidence => CONFIDENCE[:med],
47
- :file => "#{tracker.options[:app_path]}/config/routes.rb"
47
+ :file => "#{tracker.app_path}/config/routes.rb"
48
48
  end
49
49
  end
50
50
  end
@@ -76,7 +76,7 @@ class Brakeman::CheckDefaultRoutes < Brakeman::BaseCheck
76
76
  :warning_code => :CVE_2014_0130,
77
77
  :message => "Rails #{tracker.config[:rails_version]} with globbing routes is vulnerable to directory traversal and remote code execution. Patch or upgrade to #{upgrade}",
78
78
  :confidence => confidence,
79
- :file => "#{tracker.options[:app_path]}/config/routes.rb",
79
+ :file => "#{tracker.app_path}/config/routes.rb",
80
80
  :link => "http://matasano.com/research/AnatomyOfRailsVuln-CVE-2014-0130.pdf"
81
81
  end
82
82
 
@@ -9,7 +9,7 @@ class Brakeman::CheckI18nXSS < Brakeman::BaseCheck
9
9
  if (version_between? "3.0.6", "3.2.15" or version_between? "4.0.0", "4.0.1") and not has_workaround?
10
10
  message = "Rails #{tracker.config[:rails_version]} has an XSS vulnerability in i18n (CVE-2013-4491). Upgrade to Rails version "
11
11
 
12
- i18n_gem = tracker.config[:gems] && tracker.config[:gems][:i18n]
12
+ i18n_gem = tracker.config[:gems][:i18n]
13
13
 
14
14
  if version_between? "3.0.6", "3.1.99" and version_before i18n_gem, "0.5.1"
15
15
  message << "3.2.16 or i18n 0.5.1"
@@ -33,7 +33,7 @@ class Brakeman::CheckJSONParsing < Brakeman::BaseCheck
33
33
 
34
34
  #Check if `yajl` is included in Gemfile
35
35
  def uses_yajl?
36
- tracker.config[:gems] and tracker.config[:gems][:yajl]
36
+ tracker.config[:gems][:yajl]
37
37
  end
38
38
 
39
39
  #Check for `ActiveSupport::JSON.backend = "JSONGem"`
@@ -184,7 +184,6 @@ class Brakeman::CheckRedirect < Brakeman::BaseCheck
184
184
  if node_type? exp, :or
185
185
  decorated_model? exp.lhs or decorated_model? exp.rhs
186
186
  else
187
- tracker.config[:gems] and
188
187
  tracker.config[:gems][:draper] and
189
188
  call? exp and
190
189
  node_type?(exp.target, :const) and
@@ -7,8 +7,9 @@ class Brakeman::CheckSend < Brakeman::BaseCheck
7
7
  @description = "Check for unsafe use of Object#send"
8
8
 
9
9
  def run_check
10
+ @send_methods = [:send, :try, :__send__, :public_send]
10
11
  Brakeman.debug("Finding instances of #send")
11
- calls = tracker.find_call :methods => [:send, :try, :__send__, :public_send]
12
+ calls = tracker.find_call :methods => @send_methods, :nested => true
12
13
 
13
14
  calls.each do |call|
14
15
  process_result call
@@ -19,10 +20,11 @@ class Brakeman::CheckSend < Brakeman::BaseCheck
19
20
  return if duplicate? result or result[:call].original_line
20
21
  add_result result
21
22
 
22
- process_call_args result[:call]
23
- target = process result[:call].target
23
+ send_call = get_send result[:call]
24
+ process_call_args send_call
25
+ target = process send_call.target
24
26
 
25
- if input = has_immediate_user_input?(result[:call].first_arg)
27
+ if input = has_immediate_user_input?(send_call.first_arg)
26
28
  warn :result => result,
27
29
  :warning_type => "Dangerous Send",
28
30
  :warning_code => :dangerous_send,
@@ -32,4 +34,15 @@ class Brakeman::CheckSend < Brakeman::BaseCheck
32
34
  :confidence => CONFIDENCE[:high]
33
35
  end
34
36
  end
37
+
38
+ # Recursively check call chain for send call
39
+ def get_send exp
40
+ if call? exp
41
+ if @send_methods.include? exp.method
42
+ return exp
43
+ else
44
+ get_send exp.target
45
+ end
46
+ end
47
+ end
35
48
  end
@@ -20,7 +20,7 @@ class Brakeman::CheckSessionSettings < Brakeman::BaseCheck
20
20
  settings = tracker.config[:rails][:action_controller] &&
21
21
  tracker.config[:rails][:action_controller][:session]
22
22
 
23
- check_for_issues settings, "#{tracker.options[:app_path]}/config/environment.rb"
23
+ check_for_issues settings, "#{tracker.app_path}/config/environment.rb"
24
24
 
25
25
  ["session_store.rb", "secret_token.rb"].each do |file|
26
26
  if tracker.initializers[file] and not ignored? file
@@ -39,15 +39,15 @@ class Brakeman::CheckSessionSettings < Brakeman::BaseCheck
39
39
  #in Rails 4.x apps
40
40
  def process_attrasgn exp
41
41
  if not tracker.options[:rails3] and exp.target == @session_settings and exp.method == :session=
42
- check_for_issues exp.first_arg, "#{tracker.options[:app_path]}/config/initializers/session_store.rb"
42
+ check_for_issues exp.first_arg, "#{tracker.app_path}/config/initializers/session_store.rb"
43
43
  end
44
44
 
45
45
  if tracker.options[:rails3] and settings_target?(exp.target) and
46
46
  (exp.method == :secret_token= or exp.method == :secret_key_base=) and string? exp.first_arg
47
47
 
48
- warn_about_secret_token exp, "#{tracker.options[:app_path]}/config/initializers/secret_token.rb"
48
+ warn_about_secret_token exp, "#{tracker.app_path}/config/initializers/secret_token.rb"
49
49
  end
50
-
50
+
51
51
  exp
52
52
  end
53
53
 
@@ -55,9 +55,9 @@ class Brakeman::CheckSessionSettings < Brakeman::BaseCheck
55
55
  #in Rails 3.x apps
56
56
  def process_call exp
57
57
  if tracker.options[:rails3] and settings_target?(exp.target) and exp.method == :session_store
58
- check_for_rails3_issues exp.second_arg, "#{tracker.options[:app_path]}/config/initializers/session_store.rb"
58
+ check_for_rails3_issues exp.second_arg, "#{tracker.app_path}/config/initializers/session_store.rb"
59
59
  end
60
-
60
+
61
61
  exp
62
62
  end
63
63
 
@@ -134,12 +134,15 @@ class Brakeman::CheckSessionSettings < Brakeman::BaseCheck
134
134
  end
135
135
 
136
136
  def ignored? file
137
- if @app_tree.exists? ".gitignore"
138
- input = @app_tree.read(".gitignore")
137
+ [".", "config", "config/initializers"].each do |dir|
138
+ ignore_file = "#{dir}/.gitignore"
139
+ if @app_tree.exists? ignore_file
140
+ input = @app_tree.read(ignore_file)
139
141
 
140
- input.include? file
141
- else
142
- false
142
+ return true if input.include? file
143
+ end
143
144
  end
145
+
146
+ false
144
147
  end
145
148
  end
@@ -19,7 +19,7 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
19
19
  @sql_targets = [:all, :average, :calculate, :count, :count_by_sql, :exists?, :delete_all, :destroy_all,
20
20
  :find, :find_by_sql, :first, :last, :maximum, :minimum, :pluck, :sum, :update_all]
21
21
  @sql_targets.concat [:from, :group, :having, :joins, :lock, :order, :reorder, :select, :where] if tracker.options[:rails3]
22
- @sql_targets << :find_by << :find_by! if version_between? "4.0.0", "9.9.9"
22
+ @sql_targets << :find_by << :find_by! if tracker.options[:rails4]
23
23
 
24
24
  @connection_calls = [:delete, :execute, :insert, :select_all, :select_one,
25
25
  :select_rows, :select_value, :select_values]
@@ -496,23 +496,32 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
496
496
  arg = exp.first_arg
497
497
 
498
498
  if STRING_METHODS.include? method
499
- if string? target
500
- check_string_arg arg
501
- elsif string? arg
502
- check_string_arg target
503
- elsif call? target
504
- check_for_string_building target
505
- elsif node_type? target, :string_interp, :dstr or
506
- node_type? arg, :string_interp, :dstr
507
-
508
- check_string_arg target and
509
- check_string_arg arg
510
- end
499
+ check_str_target_or_arg(target, arg) or
500
+ check_interp_target_or_arg(target, arg) or
501
+ check_for_string_building(target) or
502
+ check_for_string_building(arg)
511
503
  else
512
504
  nil
513
505
  end
514
506
  end
515
507
 
508
+ def check_str_target_or_arg target, arg
509
+ if string? target
510
+ check_string_arg arg
511
+ elsif string? arg
512
+ check_string_arg target
513
+ end
514
+ end
515
+
516
+ def check_interp_target_or_arg target, arg
517
+ if node_type? target, :string_interp, :dstr or
518
+ node_type? arg, :string_interp, :dstr
519
+
520
+ check_string_arg target and
521
+ check_string_arg arg
522
+ end
523
+ end
524
+
516
525
  def check_string_arg exp
517
526
  if safe_value? exp
518
527
  nil
@@ -48,7 +48,7 @@ class Brakeman::CheckSQLCVEs < Brakeman::BaseCheck
48
48
  }
49
49
  end
50
50
 
51
- if tracker.config[:gems] and tracker.config[:gems][:pg]
51
+ if tracker.config[:gems][:pg]
52
52
  issues << {
53
53
  :cve => "CVE-2014-3482",
54
54
  :versions => [%w[2.0.0 2.9.9 3.2.19], %w[3.0.0 3.2.18 3.2.19], %w[4.0.0 4.0.6 4.0.7], %w[4.1.0 4.1.2 4.1.3]],
@@ -54,6 +54,8 @@ class Brakeman::CheckSymbolDoS < Brakeman::BaseCheck
54
54
  end
55
55
 
56
56
  if confidence
57
+ return if safe_parameter? input.match
58
+
57
59
  message = "Symbol conversion from unsafe string (#{friendly_type_of input})"
58
60
 
59
61
  warn :result => result,
@@ -63,7 +65,14 @@ class Brakeman::CheckSymbolDoS < Brakeman::BaseCheck
63
65
  :user_input => input.match,
64
66
  :confidence => confidence
65
67
  end
66
-
67
68
  end
68
69
 
70
+ def safe_parameter? input
71
+ return unless params? input
72
+
73
+ call? input and
74
+ input.method == :[] and
75
+ symbol? input.first_arg and
76
+ [:controller, :action].include? input.first_arg.value
77
+ end
69
78
  end
@@ -32,7 +32,7 @@ module Brakeman::Options
32
32
  end
33
33
 
34
34
  opts.on "-p", "--path PATH", "Specify path to Rails application" do |path|
35
- options[:app_path] = File.expand_path path
35
+ options[:app_path] = path
36
36
  end
37
37
 
38
38
  opts.on "-q", "--[no-]quiet", "Suppress informational messages" do |quiet|
@@ -47,6 +47,11 @@ module Brakeman::Options
47
47
  options[:rails3] = true
48
48
  end
49
49
 
50
+ opts.on "-4", "--rails4", "Force Rails 4 mode" do
51
+ options[:rails3] = true
52
+ options[:rails4] = true
53
+ end
54
+
50
55
  opts.separator ""
51
56
  opts.separator "Scanning options:"
52
57
 
@@ -133,6 +138,11 @@ module Brakeman::Options
133
138
  end
134
139
  end
135
140
 
141
+ opts.on "--add-checks-path path1,path2,etc", Array, "A directory containing additional out-of-tree checks to run" do |paths|
142
+ options[:additional_checks_path] ||= Set.new
143
+ options[:additional_checks_path].merge paths.map {|p| File.expand_path p}
144
+ end
145
+
136
146
  opts.separator ""
137
147
  opts.separator "Output options:"
138
148
 
@@ -39,14 +39,6 @@ class Brakeman::Rails3Erubis < ::Erubis::Eruby
39
39
  end
40
40
  end
41
41
 
42
- def add_stmt(src, code)
43
- if code =~ BLOCK_EXPR
44
- src << '@output_buffer.append_if_string= ' << code
45
- else
46
- super
47
- end
48
- end
49
-
50
42
  def add_expr_escaped(src, code)
51
43
  if code =~ BLOCK_EXPR
52
44
  src << "@output_buffer.safe_append= " << code
@@ -27,7 +27,7 @@ module Brakeman
27
27
  when :slim
28
28
  parse_slim text
29
29
  else
30
- tracker.error "Unkown template type in #{path}"
30
+ tracker.error "Unknown template type in #{path}"
31
31
  nil
32
32
  end
33
33
 
@@ -19,9 +19,15 @@ class Brakeman::GemProcessor < Brakeman::BaseProcessor
19
19
  @tracker.config[:rails_version] = $1
20
20
  end
21
21
 
22
- if @tracker.config[:rails_version] =~ /^(3|4)\./ and not @tracker.options[:rails3]
23
- @tracker.options[:rails3] = true
24
- Brakeman.notify "[Notice] Detected Rails #$1 application"
22
+ if @tracker.options[:rails3].nil? and @tracker.options[:rails4].nil? and @tracker.config[:rails_version]
23
+ if @tracker.config[:rails_version].start_with? "3"
24
+ @tracker.options[:rails3] = true
25
+ Brakeman.notify "[Notice] Detected Rails 3 application"
26
+ elsif @tracker.config[:rails_version].start_with? "4"
27
+ @tracker.options[:rails3] = true
28
+ @tracker.options[:rails4] = true
29
+ Brakeman.notify "[Notice] Detected Rails 4 application"
30
+ end
25
31
  end
26
32
 
27
33
  if @tracker.config[:gems][:rails_xss]
@@ -1,10 +1,3 @@
1
- #Temporary fix for https://github.com/seattlerb/ruby_parser/issues/154
2
- class Regexp
3
- [:ENC_NONE, :ENC_EUC, :ENC_SJIS, :ENC_UTF8].each do |enc|
4
- remove_const enc if const_defined? enc
5
- end
6
- end
7
-
8
1
  require 'ruby2ruby'
9
2
  require 'brakeman/util'
10
3
 
@@ -262,9 +262,16 @@ class Brakeman::Report::Base
262
262
  end
263
263
 
264
264
  def rails_version
265
- return tracker.config[:rails_version] if tracker.config[:rails_version]
266
- return "3.x" if tracker.options[:rails3]
267
- "Unknown"
265
+ case
266
+ when tracker.config[:rails_version]
267
+ tracker.config[:rails_version]
268
+ when tracker.options[:rails4]
269
+ "4.x"
270
+ when tracker.options[:rails3]
271
+ "3.x"
272
+ else
273
+ "Unknown"
274
+ end
268
275
  end
269
276
 
270
277
  #Escape warning message and highlight user input in text output
@@ -50,7 +50,7 @@ class Brakeman::Report::CSV < Brakeman::Report::Table
50
50
  #Generate header for CSV output
51
51
  def csv_header
52
52
  header = CSV.generate_line(["Application Path", "Report Generation Time", "Checks Performed", "Rails Version"])
53
- header << CSV.generate_line([File.expand_path(tracker.options[:app_path]), Time.now.to_s, checks.checks_run.sort.join(", "), rails_version])
53
+ header << CSV.generate_line([File.expand_path(tracker.app_path), Time.now.to_s, checks.checks_run.sort.join(", "), rails_version])
54
54
  "BRAKEMAN REPORT\n\n" + header
55
55
  end
56
56
  end
@@ -16,6 +16,7 @@ class Brakeman::Report::Hash < Brakeman::Report::Base
16
16
  end
17
17
 
18
18
  report[:config] = tracker.config
19
+ report[:checks_run] = tracker.checks.checks_run
19
20
 
20
21
  report
21
22
  end
@@ -4,14 +4,13 @@ require 'brakeman/report/initializers/multi_json'
4
4
  class Brakeman::Report::JSON < Brakeman::Report::Base
5
5
  def generate_report
6
6
  errors = tracker.errors.map{|e| { :error => e[:error], :location => e[:backtrace][0] }}
7
- app_path = tracker.options[:app_path]
8
7
 
9
8
  warnings = convert_to_hashes all_warnings
10
9
 
11
10
  ignored = convert_to_hashes ignored_warnings
12
11
 
13
12
  scan_info = {
14
- :app_path => File.expand_path(tracker.options[:app_path]),
13
+ :app_path => tracker.app_path,
15
14
  :rails_version => rails_version,
16
15
  :security_warnings => all_warnings.length,
17
16
  :start_time => tracker.start_time.to_s,
@@ -66,7 +66,7 @@ class Brakeman::Report::Markdown < Brakeman::Report::Base
66
66
  ['Application path', 'Rails version', 'Brakeman version', 'Started at', 'Duration']
67
67
  ) do |t|
68
68
  t.add_row([
69
- File.expand_path(tracker.options[:app_path]),
69
+ tracker.app_path,
70
70
  rails_version,
71
71
  Brakeman::Version,
72
72
  tracker.start_time,
@@ -98,7 +98,7 @@ class Brakeman::Report::Table < Brakeman::Report::Base
98
98
 
99
99
  +BRAKEMAN REPORT+
100
100
 
101
- Application path: #{File.expand_path tracker.options[:app_path]}
101
+ Application path: #{tracker.app_path}
102
102
  Rails version: #{rails_version}
103
103
  Brakeman version: #{Brakeman::Version}
104
104
  Started at #{tracker.start_time}
@@ -31,7 +31,7 @@
31
31
  <th>Checks Performed</th>
32
32
  </tr>
33
33
  <tr>
34
- <td><%= File.expand_path tracker.options[:app_path] %></td>
34
+ <td><%= tracker.app_path %></td>
35
35
  <td><%= rails_version %></td>
36
36
  <td><%= brakeman_version %>
37
37
  <td>
@@ -28,14 +28,6 @@ class Brakeman::Scanner
28
28
  raise Brakeman::NoApplication, "Please supply the path to a Rails application."
29
29
  end
30
30
 
31
- if @app_tree.exists?("script/rails")
32
- options[:rails3] = true
33
- Brakeman.notify "[Notice] Detected Rails 3 application"
34
- elsif not @app_tree.exists?("script")
35
- options[:rails3] = true # Probably need to do some refactoring
36
- Brakeman.notify "[Notice] Detected Rails 4 application"
37
- end
38
-
39
31
  @processor = processor || Brakeman::Processor.new(@app_tree, options)
40
32
  end
41
33
 
@@ -48,6 +40,7 @@ class Brakeman::Scanner
48
40
  def process
49
41
  Brakeman.notify "Processing gems..."
50
42
  process_gems
43
+ guess_rails_version
51
44
  Brakeman.notify "Processing configuration..."
52
45
  process_config
53
46
  Brakeman.notify "Parsing files..."
@@ -147,6 +140,20 @@ class Brakeman::Scanner
147
140
  tracker.error e.exception(e.message + "\nWhile processing Gemfile"), e.backtrace
148
141
  end
149
142
 
143
+ #Set :rails3/:rails4 option if version was not determined from Gemfile
144
+ def guess_rails_version
145
+ unless tracker.options[:rails3] or tracker.options[:rails4]
146
+ if @app_tree.exists?("script/rails")
147
+ tracker.options[:rails3] = true
148
+ Brakeman.notify "[Notice] Detected Rails 3 application"
149
+ elsif not @app_tree.exists?("script")
150
+ tracker.options[:rails3] = true # Probably need to do some refactoring
151
+ tracker.options[:rails4] = true
152
+ Brakeman.notify "[Notice] Detected Rails 4 application"
153
+ end
154
+ end
155
+ end
156
+
150
157
  #Process all the .rb files in config/initializers/
151
158
  #
152
159
  #Adds parsed information to tracker.initializers
@@ -227,7 +234,7 @@ class Brakeman::Scanner
227
234
  begin
228
235
  @processor.process_controller(astfile.ast, astfile.path)
229
236
  rescue => e
230
- tracker.error e.exception(e.message + "\nWhile processing #{path}"), e.backtrace
237
+ tracker.error e.exception(e.message + "\nWhile processing #{astfile.path}"), e.backtrace
231
238
  end
232
239
  end
233
240
 
@@ -25,7 +25,7 @@ class Brakeman::Tracker
25
25
  @processor = processor
26
26
  @options = options
27
27
 
28
- @config = { :rails => {} }
28
+ @config = { :rails => {}, :gems => {} }
29
29
  @templates = {}
30
30
  @controllers = {}
31
31
  #Initialize models with the unknown model so
@@ -77,6 +77,10 @@ class Brakeman::Tracker
77
77
  @checks
78
78
  end
79
79
 
80
+ def app_path
81
+ @app_path ||= File.expand_path @options[:app_path]
82
+ end
83
+
80
84
  #Iterate over all methods in controllers and models.
81
85
  def each_method
82
86
  [self.controllers, self.models].each do |set|
data/lib/brakeman/util.rb CHANGED
@@ -274,7 +274,7 @@ module Brakeman::Util
274
274
  end
275
275
 
276
276
  if warning.file
277
- File.expand_path warning.file, tracker.options[:app_path]
277
+ File.expand_path warning.file, tracker.app_path
278
278
  elsif warning.template.is_a? Hash and warning.template[:file]
279
279
  warning.template[:file]
280
280
  else
@@ -314,7 +314,7 @@ module Brakeman::Util
314
314
  end
315
315
  end
316
316
 
317
- path = tracker.options[:app_path]
317
+ path = tracker.app_path
318
318
 
319
319
  case type
320
320
  when :controller
@@ -377,7 +377,7 @@ module Brakeman::Util
377
377
 
378
378
  def relative_path file
379
379
  if file and not file.empty? and file.start_with? '/'
380
- Pathname.new(file).relative_path_from(Pathname.new(@tracker.options[:app_path])).to_s
380
+ Pathname.new(file).relative_path_from(Pathname.new(@tracker.app_path)).to_s
381
381
  else
382
382
  file
383
383
  end
@@ -1,3 +1,3 @@
1
1
  module Brakeman
2
- Version = "2.6.1"
2
+ Version = "2.6.2"
3
3
  end
@@ -81,6 +81,8 @@ module Brakeman::WarningCodes
81
81
  :CVE_2014_0130 => 77,
82
82
  :CVE_2014_3482 => 78,
83
83
  :CVE_2014_3483 => 79,
84
+ :CVE_2014_3514 => 80,
85
+ :CVE_2014_3514_call => 81,
84
86
  }
85
87
 
86
88
  def self.code name
@@ -12,7 +12,14 @@ class Sexp
12
12
  #
13
13
  #The original functionality calls find_node and optionally
14
14
  #deletes the node if found.
15
- raise NoMethodError.new("No method '#{name}' for Sexp", name, args)
15
+ #
16
+ #Defining a method named "return" seems like a bad idea, so we have to
17
+ #check for it here instead
18
+ if name == :return
19
+ find_node name, *args
20
+ else
21
+ raise NoMethodError.new("No method '#{name}' for Sexp", name, args)
22
+ end
16
23
  end
17
24
 
18
25
  #Create clone of Sexp and nested Sexps but not their non-Sexp contents.
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brakeman
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.6.1
5
- prerelease:
4
+ version: 2.6.2
6
5
  platform: ruby
7
6
  authors:
8
7
  - Justin Collins
@@ -36,78 +35,95 @@ cert_chain:
36
35
  Q0c3bUZaNnhnaDAxZXFuWlVzTmQ4dk0rNlY2djIzVnUKamsydE1qRlQ0TDFk
37
36
  QTNNRXN6MytNUDE0NFBEaFBDaDd0UGU2eXk4MUJPdnlZVFZrS3pyQWtnS3dI
38
37
  RDFDdXZzSApiZHc9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
39
- date: 2014-07-02 00:00:00.000000000 Z
38
+ date: 2014-08-18 00:00:00.000000000 Z
40
39
  dependencies:
41
40
  - !ruby/object:Gem::Dependency
42
41
  name: ruby_parser
43
- requirement: &70322329568880 !ruby/object:Gem::Requirement
44
- none: false
42
+ requirement: !ruby/object:Gem::Requirement
45
43
  requirements:
46
44
  - - ~>
47
45
  - !ruby/object:Gem::Version
48
46
  version: 3.5.0
49
47
  type: :runtime
50
48
  prerelease: false
51
- version_requirements: *70322329568880
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 3.5.0
52
54
  - !ruby/object:Gem::Dependency
53
55
  name: ruby2ruby
54
- requirement: &70322329568380 !ruby/object:Gem::Requirement
55
- none: false
56
+ requirement: !ruby/object:Gem::Requirement
56
57
  requirements:
57
58
  - - ~>
58
59
  - !ruby/object:Gem::Version
59
- version: 2.0.5
60
+ version: 2.1.1
60
61
  type: :runtime
61
62
  prerelease: false
62
- version_requirements: *70322329568380
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ~>
66
+ - !ruby/object:Gem::Version
67
+ version: 2.1.1
63
68
  - !ruby/object:Gem::Dependency
64
69
  name: terminal-table
65
- requirement: &70322329567880 !ruby/object:Gem::Requirement
66
- none: false
70
+ requirement: !ruby/object:Gem::Requirement
67
71
  requirements:
68
72
  - - ~>
69
73
  - !ruby/object:Gem::Version
70
74
  version: '1.4'
71
75
  type: :runtime
72
76
  prerelease: false
73
- version_requirements: *70322329567880
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ~>
80
+ - !ruby/object:Gem::Version
81
+ version: '1.4'
74
82
  - !ruby/object:Gem::Dependency
75
83
  name: fastercsv
76
- requirement: &70322329567300 !ruby/object:Gem::Requirement
77
- none: false
84
+ requirement: !ruby/object:Gem::Requirement
78
85
  requirements:
79
86
  - - ~>
80
87
  - !ruby/object:Gem::Version
81
88
  version: '1.5'
82
89
  type: :runtime
83
90
  prerelease: false
84
- version_requirements: *70322329567300
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ~>
94
+ - !ruby/object:Gem::Version
95
+ version: '1.5'
85
96
  - !ruby/object:Gem::Dependency
86
97
  name: highline
87
- requirement: &70322329566800 !ruby/object:Gem::Requirement
88
- none: false
98
+ requirement: !ruby/object:Gem::Requirement
89
99
  requirements:
90
100
  - - ~>
91
101
  - !ruby/object:Gem::Version
92
102
  version: 1.6.20
93
103
  type: :runtime
94
104
  prerelease: false
95
- version_requirements: *70322329566800
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: 1.6.20
96
110
  - !ruby/object:Gem::Dependency
97
111
  name: erubis
98
- requirement: &70322329566300 !ruby/object:Gem::Requirement
99
- none: false
112
+ requirement: !ruby/object:Gem::Requirement
100
113
  requirements:
101
114
  - - ~>
102
115
  - !ruby/object:Gem::Version
103
116
  version: '2.6'
104
117
  type: :runtime
105
118
  prerelease: false
106
- version_requirements: *70322329566300
119
+ version_requirements: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ~>
122
+ - !ruby/object:Gem::Version
123
+ version: '2.6'
107
124
  - !ruby/object:Gem::Dependency
108
125
  name: haml
109
- requirement: &70322329565820 !ruby/object:Gem::Requirement
110
- none: false
126
+ requirement: !ruby/object:Gem::Requirement
111
127
  requirements:
112
128
  - - ! '>='
113
129
  - !ruby/object:Gem::Version
@@ -117,22 +133,31 @@ dependencies:
117
133
  version: '5.0'
118
134
  type: :runtime
119
135
  prerelease: false
120
- version_requirements: *70322329565820
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ! '>='
139
+ - !ruby/object:Gem::Version
140
+ version: '3.0'
141
+ - - <
142
+ - !ruby/object:Gem::Version
143
+ version: '5.0'
121
144
  - !ruby/object:Gem::Dependency
122
145
  name: sass
123
- requirement: &70322329565100 !ruby/object:Gem::Requirement
124
- none: false
146
+ requirement: !ruby/object:Gem::Requirement
125
147
  requirements:
126
148
  - - ~>
127
149
  - !ruby/object:Gem::Version
128
150
  version: '3.0'
129
151
  type: :runtime
130
152
  prerelease: false
131
- version_requirements: *70322329565100
153
+ version_requirements: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - ~>
156
+ - !ruby/object:Gem::Version
157
+ version: '3.0'
132
158
  - !ruby/object:Gem::Dependency
133
159
  name: slim
134
- requirement: &70322329564620 !ruby/object:Gem::Requirement
135
- none: false
160
+ requirement: !ruby/object:Gem::Requirement
136
161
  requirements:
137
162
  - - ! '>='
138
163
  - !ruby/object:Gem::Version
@@ -142,18 +167,28 @@ dependencies:
142
167
  version: '3.0'
143
168
  type: :runtime
144
169
  prerelease: false
145
- version_requirements: *70322329564620
170
+ version_requirements: !ruby/object:Gem::Requirement
171
+ requirements:
172
+ - - ! '>='
173
+ - !ruby/object:Gem::Version
174
+ version: 1.3.6
175
+ - - <
176
+ - !ruby/object:Gem::Version
177
+ version: '3.0'
146
178
  - !ruby/object:Gem::Dependency
147
179
  name: multi_json
148
- requirement: &70322329580140 !ruby/object:Gem::Requirement
149
- none: false
180
+ requirement: !ruby/object:Gem::Requirement
150
181
  requirements:
151
182
  - - ~>
152
183
  - !ruby/object:Gem::Version
153
184
  version: '1.2'
154
185
  type: :runtime
155
186
  prerelease: false
156
- version_requirements: *70322329580140
187
+ version_requirements: !ruby/object:Gem::Requirement
188
+ requirements:
189
+ - - ~>
190
+ - !ruby/object:Gem::Version
191
+ version: '1.2'
157
192
  description: Brakeman detects security vulnerabilities in Ruby on Rails applications
158
193
  via static analysis.
159
194
  email: gem@brakeman.org
@@ -162,17 +197,20 @@ executables:
162
197
  extensions: []
163
198
  extra_rdoc_files: []
164
199
  files:
165
- - bin/brakeman
166
200
  - CHANGES
167
- - WARNING_TYPES
168
201
  - FEATURES
169
202
  - README.md
203
+ - WARNING_TYPES
204
+ - bin/brakeman
205
+ - lib/brakeman.rb
170
206
  - lib/brakeman/app_tree.rb
171
207
  - lib/brakeman/brakeman.rake
172
208
  - lib/brakeman/call_index.rb
209
+ - lib/brakeman/checks.rb
173
210
  - lib/brakeman/checks/base_check.rb
174
211
  - lib/brakeman/checks/check_basic_auth.rb
175
212
  - lib/brakeman/checks/check_content_tag.rb
213
+ - lib/brakeman/checks/check_create_with.rb
176
214
  - lib/brakeman/checks/check_cross_site_scripting.rb
177
215
  - lib/brakeman/checks/check_default_routes.rb
178
216
  - lib/brakeman/checks/check_deserialize.rb
@@ -223,7 +261,6 @@ files:
223
261
  - lib/brakeman/checks/check_validation_regex.rb
224
262
  - lib/brakeman/checks/check_without_protection.rb
225
263
  - lib/brakeman/checks/check_yaml_parsing.rb
226
- - lib/brakeman/checks.rb
227
264
  - lib/brakeman/differ.rb
228
265
  - lib/brakeman/file_parser.rb
229
266
  - lib/brakeman/format/style.css
@@ -259,6 +296,7 @@ files:
259
296
  - lib/brakeman/processors/slim_template_processor.rb
260
297
  - lib/brakeman/processors/template_alias_processor.rb
261
298
  - lib/brakeman/processors/template_processor.rb
299
+ - lib/brakeman/report.rb
262
300
  - lib/brakeman/report/ignore/config.rb
263
301
  - lib/brakeman/report/ignore/interactive.rb
264
302
  - lib/brakeman/report/initializers/faster_csv.rb
@@ -283,7 +321,6 @@ files:
283
321
  - lib/brakeman/report/templates/template_overview.html.erb
284
322
  - lib/brakeman/report/templates/view_warnings.html.erb
285
323
  - lib/brakeman/report/templates/warning_overview.html.erb
286
- - lib/brakeman/report.rb
287
324
  - lib/brakeman/rescanner.rb
288
325
  - lib/brakeman/scanner.rb
289
326
  - lib/brakeman/tracker.rb
@@ -291,32 +328,30 @@ files:
291
328
  - lib/brakeman/version.rb
292
329
  - lib/brakeman/warning.rb
293
330
  - lib/brakeman/warning_codes.rb
294
- - lib/brakeman.rb
295
331
  - lib/ruby_parser/bm_sexp.rb
296
332
  - lib/ruby_parser/bm_sexp_processor.rb
297
333
  homepage: http://brakemanscanner.org
298
334
  licenses:
299
335
  - MIT
336
+ metadata: {}
300
337
  post_install_message:
301
338
  rdoc_options: []
302
339
  require_paths:
303
340
  - lib
304
341
  required_ruby_version: !ruby/object:Gem::Requirement
305
- none: false
306
342
  requirements:
307
343
  - - ! '>='
308
344
  - !ruby/object:Gem::Version
309
345
  version: '0'
310
346
  required_rubygems_version: !ruby/object:Gem::Requirement
311
- none: false
312
347
  requirements:
313
348
  - - ! '>='
314
349
  - !ruby/object:Gem::Version
315
350
  version: '0'
316
351
  requirements: []
317
352
  rubyforge_project:
318
- rubygems_version: 1.8.9
353
+ rubygems_version: 2.3.0
319
354
  signing_key:
320
- specification_version: 3
355
+ specification_version: 4
321
356
  summary: Security vulnerability scanner for Ruby on Rails.
322
357
  test_files: []
metadata.gz.sig CHANGED
Binary file