brakeman 2.6.1 → 2.6.2

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