brakeman-min 3.2.1 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +18 -0
  3. data/bin/brakeman +1 -1
  4. data/lib/brakeman.rb +9 -1
  5. data/lib/brakeman/call_index.rb +1 -1
  6. data/lib/brakeman/checks/check_content_tag.rb +1 -1
  7. data/lib/brakeman/checks/check_cross_site_scripting.rb +1 -1
  8. data/lib/brakeman/checks/check_execute.rb +4 -0
  9. data/lib/brakeman/checks/check_forgery_setting.rb +3 -2
  10. data/lib/brakeman/checks/check_link_to.rb +1 -1
  11. data/lib/brakeman/checks/check_link_to_href.rb +2 -2
  12. data/lib/brakeman/checks/check_mass_assignment.rb +1 -1
  13. data/lib/brakeman/checks/check_redirect.rb +6 -0
  14. data/lib/brakeman/checks/check_secrets.rb +40 -0
  15. data/lib/brakeman/checks/check_sql.rb +1 -1
  16. data/lib/brakeman/processor.rb +6 -6
  17. data/lib/brakeman/processors/alias_processor.rb +29 -3
  18. data/lib/brakeman/processors/base_processor.rb +35 -4
  19. data/lib/brakeman/processors/controller_alias_processor.rb +4 -4
  20. data/lib/brakeman/processors/haml_template_processor.rb +1 -1
  21. data/lib/brakeman/processors/lib/basic_processor.rb +18 -0
  22. data/lib/brakeman/processors/lib/rails2_config_processor.rb +3 -2
  23. data/lib/brakeman/processors/lib/rails2_route_processor.rb +2 -1
  24. data/lib/brakeman/processors/lib/rails3_config_processor.rb +3 -2
  25. data/lib/brakeman/processors/lib/rails3_route_processor.rb +2 -1
  26. data/lib/brakeman/processors/template_alias_processor.rb +4 -4
  27. data/lib/brakeman/processors/template_processor.rb +1 -0
  28. data/lib/brakeman/report/report_codeclimate.rb +2 -1
  29. data/lib/brakeman/scanner.rb +1 -1
  30. data/lib/brakeman/tracker.rb +11 -1
  31. data/lib/brakeman/tracker/constants.rb +101 -0
  32. data/lib/brakeman/util.rb +4 -0
  33. data/lib/brakeman/version.rb +1 -1
  34. data/lib/brakeman/warning_codes.rb +1 -0
  35. data/lib/ruby_parser/bm_sexp.rb +6 -0
  36. metadata +5 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 17de56675dc2f00c7a1b4c10e833501ac3b039c2
4
- data.tar.gz: 8c9399690ad552f470057f3945248784e1ff7cb4
3
+ metadata.gz: bfbe9bf6ab37921809b33145342e4bcd6df55e8e
4
+ data.tar.gz: 62f41f3c6a63e4f1b9c662b28779cb821d60a7b9
5
5
  SHA512:
6
- metadata.gz: ab231cd491eb31cab3ab399788c2bfab81dd1a79a231bb303e409ab67e66688ba6b2044884f6fb2418c2b408c8f33e69dd7d6cde9188aa9122c4b7647c01de78
7
- data.tar.gz: cb931ae85cf06d0607a25d6c4ce10f5f82b11e5a8e7bfa9f31a70a49f72aa769602f8868756f2fb21972ee21cc7cd0555241654bf961859ee0a76e5913d4645b
6
+ metadata.gz: 3724d2c9aad208a2c5197decc4e72e46e9306a7745aaecdd6326bb8357367941b6f14586163bab5e299928cec1acb1d4f994f884441b78f521580cc0b26cbbcf
7
+ data.tar.gz: 26f0ab2c6871b2a304773c7d93c1b25e2958adef16f97d96257a39ba8cf1c085c1451e5180754e2ae18f197b7b5efc2370e081bd21ec6cb2ab17bb9bc554321d
data/CHANGES CHANGED
@@ -1,3 +1,21 @@
1
+ # 3.3.0
2
+
3
+ * Skip processing obviously false if branches (more broadly)
4
+ * Skip if branches with `Rails.env.test?`
5
+ * Return exit code `4` if no Rails application is detected
6
+ * Avoid warning about mass assignment with `params.slice`
7
+ * Avoid warning about `u` helper (Chad Dollins)
8
+ * Add optional check for secrets in source code
9
+ * Process `Array#first`
10
+ * Allow non-Hash arguments in `protect_from_forgery` (Jason Yeo)
11
+ * Avoid warning on `popen` with array
12
+ * Bundle all dependencies in gem
13
+ * Track constants globally
14
+ * Handle HAML `find_and_preserve` with a block
15
+ * [Code Climate engine] When possible, output to /dev/stdout (Gordon Diggs)
16
+ * [Code Climate engine] Remove nil entries from include_paths (Gordon Diggs)
17
+ * [Code Climate engine] Report end lines for issues (Gordon Diggs)
18
+
1
19
  # 3.2.1
2
20
 
3
21
  * Remove `multi_json` dependency from `bin/brakeman`
data/bin/brakeman CHANGED
@@ -85,5 +85,5 @@ begin
85
85
  end
86
86
  rescue Brakeman::NoApplication => e
87
87
  $stderr.puts e.message
88
- exit 1
88
+ exit Brakeman::No_App_Found_Exit_Code
89
89
  end
data/lib/brakeman.rb CHANGED
@@ -1,12 +1,20 @@
1
- require 'rubygems'
2
1
  require 'set'
3
2
 
3
+ path_load = "#{File.expand_path(File.dirname(__FILE__))}/../bundle/load.rb"
4
+
5
+ if File.exist? path_load
6
+ require path_load
7
+ end
8
+
4
9
  module Brakeman
5
10
 
6
11
  #This exit code is used when warnings are found and the --exit-on-warn
7
12
  #option is set
8
13
  Warnings_Found_Exit_Code = 3
9
14
 
15
+ #Exit code returned when no Rails application is detected
16
+ No_App_Found_Exit_Code = 4
17
+
10
18
  @debug = false
11
19
  @quiet = false
12
20
  @loaded_dependencies = []
@@ -53,7 +53,7 @@ class Brakeman::CallIndex
53
53
  elsif method
54
54
  calls = calls_by_method method
55
55
  else
56
- notify "Invalid arguments to CallCache#find_calls: #{options.inspect}"
56
+ raise "Invalid arguments to CallCache#find_calls: #{options.inspect}"
57
57
  end
58
58
 
59
59
  return [] if calls.nil?
@@ -24,7 +24,7 @@ class Brakeman::CheckContentTag < Brakeman::CheckCrossSiteScripting
24
24
  :hidden_field, :hidden_field_tag, :image_tag, :label,
25
25
  :mail_to, :radio_button, :select,
26
26
  :submit_tag, :text_area, :text_field,
27
- :text_field_tag, :url_encode, :url_for,
27
+ :text_field_tag, :url_encode, :u, :url_for,
28
28
  :will_paginate].merge tracker.options[:safe_methods]
29
29
 
30
30
  @known_dangerous = []
@@ -286,7 +286,7 @@ class Brakeman::CheckCrossSiteScripting < Brakeman::BaseCheck
286
286
  :hidden_field, :hidden_field_tag, :image_tag, :label,
287
287
  :link_to, :mail_to, :radio_button, :select,
288
288
  :submit_tag, :text_area, :text_field,
289
- :text_field_tag, :url_encode, :url_for,
289
+ :text_field_tag, :url_encode, :u, :url_for,
290
290
  :will_paginate].merge tracker.options[:safe_methods]
291
291
 
292
292
  @models = tracker.models.keys
@@ -43,6 +43,10 @@ class Brakeman::CheckExecute < Brakeman::BaseCheck
43
43
  first_arg = call.first_arg
44
44
 
45
45
  case call.method
46
+ when :popen
47
+ unless array? first_arg
48
+ failure = include_user_input?(args) || dangerous_interp?(args)
49
+ end
46
50
  when :system, :exec
47
51
  failure = include_user_input?(first_arg) || dangerous_interp?(first_arg)
48
52
  else
@@ -13,7 +13,7 @@ class Brakeman::CheckForgerySetting < Brakeman::BaseCheck
13
13
  app_controller = tracker.controllers[:ApplicationController]
14
14
  return unless app_controller and app_controller.ancestor? :"ActionController::Base"
15
15
 
16
- if tracker.config.allow_forgery_protection?
16
+ if tracker.config.allow_forgery_protection?
17
17
  warn :controller => :ApplicationController,
18
18
  :warning_type => "Cross-Site Request Forgery",
19
19
  :warning_code => :csrf_protection_disabled,
@@ -53,7 +53,8 @@ class Brakeman::CheckForgerySetting < Brakeman::BaseCheck
53
53
  elsif version_between? "4.0.0", "100.0.0" and forgery_opts = app_controller.options[:protect_from_forgery]
54
54
 
55
55
  unless forgery_opts.is_a?(Array) and sexp?(forgery_opts.first) and
56
- access_arg = hash_access(forgery_opts.first.first_arg, :with) and access_arg.value == :exception
56
+ access_arg = hash_access(forgery_opts.first.first_arg, :with) and symbol? access_arg and
57
+ access_arg.value == :exception
57
58
 
58
59
  args = {
59
60
  :controller => :ApplicationController,
@@ -17,7 +17,7 @@ class Brakeman::CheckLinkTo < Brakeman::CheckCrossSiteScripting
17
17
  :hidden_field, :hidden_field_tag, :image_tag, :label,
18
18
  :mail_to, :radio_button, :select,
19
19
  :submit_tag, :text_area, :text_field,
20
- :text_field_tag, :url_encode, :url_for,
20
+ :text_field_tag, :url_encode, :u, :url_for,
21
21
  :will_paginate].merge tracker.options[:safe_methods]
22
22
 
23
23
  @known_dangerous = []
@@ -15,9 +15,9 @@ class Brakeman::CheckLinkToHref < Brakeman::CheckLinkTo
15
15
  @ignore_methods = Set[:button_to, :check_box,
16
16
  :field_field, :fields_for, :hidden_field,
17
17
  :hidden_field, :hidden_field_tag, :image_tag, :label,
18
- :mail_to, :polymorphic_url, :radio_button, :select,
18
+ :mail_to, :polymorphic_url, :radio_button, :select, :slice,
19
19
  :submit_tag, :text_area, :text_field,
20
- :text_field_tag, :url_encode, :url_for,
20
+ :text_field_tag, :url_encode, :u, :url_for,
21
21
  :will_paginate].merge(tracker.options[:url_safe_methods] || [])
22
22
 
23
23
  @models = tracker.models.keys
@@ -160,7 +160,7 @@ class Brakeman::CheckMassAssignment < Brakeman::BaseCheck
160
160
  # Look for and warn about uses of Parameters#permit! for mass assignment
161
161
  def check_permit!
162
162
  tracker.find_call(:method => :permit!).each do |result|
163
- if params? result[:call].target
163
+ if params? result[:call].target and not result[:chain].include? :slice
164
164
  warn_on_permit! result
165
165
  end
166
166
  end
@@ -38,6 +38,7 @@ class Brakeman::CheckRedirect < Brakeman::BaseCheck
38
38
  if method == :redirect_to and
39
39
  not only_path?(call) and
40
40
  not explicit_host?(call.first_arg) and
41
+ not slice_call?(call.first_arg) and
41
42
  res = include_user_input?(call)
42
43
 
43
44
  add_result result
@@ -206,4 +207,9 @@ class Brakeman::CheckRedirect < Brakeman::BaseCheck
206
207
 
207
208
  model.association? meth
208
209
  end
210
+
211
+ def slice_call? exp
212
+ return unless call? exp
213
+ exp.method == :slice
214
+ end
209
215
  end
@@ -0,0 +1,40 @@
1
+ require 'brakeman/checks/base_check'
2
+
3
+ class Brakeman::CheckSecrets < Brakeman::BaseCheck
4
+ Brakeman::Checks.add_optional self
5
+
6
+ @description = "Checks for secrets stored in source code"
7
+
8
+ def run_check
9
+ check_constants
10
+ end
11
+
12
+ def check_constants
13
+ @warned = Set.new
14
+
15
+ @tracker.constants.each do |constant|
16
+ name = constant.name.last
17
+ value = constant.value
18
+
19
+ if string? value and not value.value.empty? and looks_like_secret? name
20
+ match = [name, value, value.line]
21
+
22
+ unless @warned.include? match
23
+ @warned << match
24
+
25
+ warn :warning_code => :secret_in_source,
26
+ :warning_type => "Authentication",
27
+ :message => "Hardcoded value for #{name} in source code",
28
+ :confidence => CONFIDENCE[:med],
29
+ :file => constant.file,
30
+ :line => constant.line
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ def looks_like_secret? name
37
+ # REST_AUTH_SITE_KEY is the pepper in Devise
38
+ name.match /password|secret|(rest_auth_site|api)_key$/i
39
+ end
40
+ end
@@ -264,7 +264,7 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
264
264
  end
265
265
 
266
266
  if request_value? arg
267
- unless call? arg and params? arg.target and arg.method == :permit
267
+ unless call? arg and params? arg.target and [:permit, :slice].include? arg.method
268
268
  # Model.where(params[:where])
269
269
  arg
270
270
  end
@@ -22,8 +22,8 @@ module Brakeman
22
22
  end
23
23
 
24
24
  #Process configuration file source
25
- def process_config src
26
- ConfigProcessor.new(@tracker).process_config src
25
+ def process_config src, file_name
26
+ ConfigProcessor.new(@tracker).process_config src, file_name
27
27
  end
28
28
 
29
29
  #Process Gemfile
@@ -88,10 +88,10 @@ module Brakeman
88
88
  end
89
89
 
90
90
  #Process source for initializing files
91
- def process_initializer name, src
92
- res = BaseProcessor.new(@tracker).process src
93
- res = AliasProcessor.new(@tracker).process res
94
- @tracker.initializers[Pathname.new(name).basename.to_s] = res
91
+ def process_initializer file_name, src
92
+ res = BaseProcessor.new(@tracker).process_file src, file_name
93
+ res = AliasProcessor.new(@tracker).process_safely res, nil, file_name
94
+ @tracker.initializers[Pathname.new(file_name).basename.to_s] = res
95
95
  end
96
96
 
97
97
  #Process source for a library file
@@ -16,7 +16,7 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
16
16
  #The recommended usage is:
17
17
  #
18
18
  # AliasProcessor.new.process_safely src
19
- def initialize tracker = nil
19
+ def initialize tracker = nil, file_name = nil
20
20
  super()
21
21
  @env = SexpProcessor::Environment.new
22
22
  @inside_if = false
@@ -28,6 +28,7 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
28
28
  @helper_method_info = Hash.new({})
29
29
  @or_depth_limit = (tracker && tracker.options[:branch_limit]) || 5 #arbitrary default
30
30
  @meth_env = nil
31
+ @file_name = file_name
31
32
  set_env_defaults
32
33
  end
33
34
 
@@ -39,7 +40,8 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
39
40
  #
40
41
  #This method returns a new Sexp with variables replaced with their values,
41
42
  #where possible.
42
- def process_safely src, set_env = nil
43
+ def process_safely src, set_env = nil, file_name = nil
44
+ @file_name = file_name
43
45
  @env = set_env || SexpProcessor::Environment.new
44
46
  @result = src.deep_clone
45
47
  process @result
@@ -73,8 +75,11 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
73
75
  def replace exp, int = 0
74
76
  return exp if int > 3
75
77
 
78
+
76
79
  if replacement = env[exp] and not duplicate? replacement
77
80
  replace(replacement.deep_clone(exp.line), int + 1)
81
+ elsif tracker and replacement = tracker.constant_lookup(exp) and not duplicate? replacement
82
+ replace(replacement.deep_clone(exp.line), int + 1)
78
83
  else
79
84
  exp
80
85
  end
@@ -82,6 +87,7 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
82
87
 
83
88
  ARRAY_CONST = s(:const, :Array)
84
89
  HASH_CONST = s(:const, :Hash)
90
+ RAILS_TEST = s(:call, s(:call, s(:const, :Rails), :env), :test?)
85
91
 
86
92
  #Process a method call.
87
93
  def process_call exp
@@ -110,8 +116,11 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
110
116
  return Sexp.new(:array, *exp.args)
111
117
  elsif target == HASH_CONST and method == :new and first_arg.nil? and !node_type?(@exp_context.last, :iter)
112
118
  return Sexp.new(:hash)
119
+ elsif exp == RAILS_TEST
120
+ return Sexp.new(:false)
113
121
  end
114
122
 
123
+
115
124
  #See if it is possible to simplify some basic cases
116
125
  #of addition/concatenation.
117
126
  case method
@@ -204,6 +213,10 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
204
213
  target = find_push_target(target_var)
205
214
  env[target] = exp unless target.nil? # Happens in TemplateAliasProcessor
206
215
  end
216
+ when :first
217
+ if array? target and first_arg.nil? and sexp? target[1]
218
+ exp = target[1]
219
+ end
207
220
  end
208
221
 
209
222
  exp
@@ -504,6 +517,19 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
504
517
  exp.rhs = process exp.rhs
505
518
  end
506
519
 
520
+ file = case
521
+ when @file_name
522
+ @file_name
523
+ when @current_class.is_a?(Brakeman::Collection)
524
+ @current_class.file
525
+ when @current_module.is_a?(Brakeman::Collection)
526
+ @current_module.file
527
+ else
528
+ nil
529
+ end
530
+
531
+ @tracker.add_constant exp.lhs, exp.rhs, :file => file if @tracker
532
+
507
533
  if exp.lhs.is_a? Symbol
508
534
  match = Sexp.new(:const, exp.lhs)
509
535
  else
@@ -543,7 +569,7 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
543
569
  @ignore_ifs = @tracker && @tracker.options[:ignore_ifs]
544
570
  end
545
571
 
546
- condition = process exp.condition
572
+ condition = exp.condition = process exp.condition
547
573
 
548
574
  #Check if a branch is obviously going to be taken
549
575
  if true? condition
@@ -13,7 +13,12 @@ class Brakeman::BaseProcessor < Brakeman::SexpProcessor
13
13
  super()
14
14
  @last = nil
15
15
  @tracker = tracker
16
- @current_template = @current_module = @current_class = @current_method = nil
16
+ @current_template = @current_module = @current_class = @current_method = @file_name = nil
17
+ end
18
+
19
+ def process_file exp, file_name
20
+ @file_name = file_name
21
+ process exp
17
22
  end
18
23
 
19
24
  def ignore
@@ -43,9 +48,19 @@ class Brakeman::BaseProcessor < Brakeman::SexpProcessor
43
48
  #Process an if statement.
44
49
  def process_if exp
45
50
  exp = exp.dup
46
- exp[1] = process exp.condition
47
- exp[2] = process exp.then_clause if exp.then_clause
48
- exp[3] = process exp.else_clause if exp.else_clause
51
+ condition = exp[1] = process exp.condition
52
+
53
+ if true? condition
54
+ exp[2] = process exp.then_clause if exp.then_clause
55
+ exp[3] = nil
56
+ elsif false? condition
57
+ exp[2] = nil
58
+ exp[3] = process exp.else_clause if exp.else_clause
59
+ else
60
+ exp[2] = process exp.then_clause if exp.then_clause
61
+ exp[3] = process exp.else_clause if exp.else_clause
62
+ end
63
+
49
64
  exp
50
65
  end
51
66
 
@@ -173,6 +188,22 @@ class Brakeman::BaseProcessor < Brakeman::SexpProcessor
173
188
  exp
174
189
  end
175
190
 
191
+ def process_cdecl exp
192
+ file = case
193
+ when @file_name
194
+ @file_name
195
+ when @current_class.is_a?(Brakeman::Collection)
196
+ @current_class.file
197
+ when @current_module.is_a?(Brakeman::Collection)
198
+ @current_module.file
199
+ else
200
+ nil
201
+ end
202
+
203
+ @tracker.add_constant exp.lhs, exp.rhs, :file => file if @tracker
204
+ exp
205
+ end
206
+
176
207
  #Convenience method for `make_render exp, true`
177
208
  def make_render_in_view exp
178
209
  make_render exp, true
@@ -20,13 +20,13 @@ class Brakeman::ControllerAliasProcessor < Brakeman::AliasProcessor
20
20
  @method_cache = {} #Cache method lookups
21
21
  end
22
22
 
23
- def process_controller name, src, file
23
+ def process_controller name, src, file_name
24
24
  if not node_type? src, :class
25
25
  Brakeman.debug "#{name} is not a class, it's a #{src.node_type}"
26
26
  return
27
27
  else
28
28
  @current_class = name
29
- @file = file
29
+ @file_name = file_name
30
30
 
31
31
  process_default src
32
32
 
@@ -59,7 +59,7 @@ class Brakeman::ControllerAliasProcessor < Brakeman::AliasProcessor
59
59
  method = processor.process method
60
60
  end
61
61
 
62
- @file = mixin.file
62
+ @file_name = mixin.file
63
63
  #Then process it like any other method in the controller
64
64
  process method
65
65
  end
@@ -182,7 +182,7 @@ class Brakeman::ControllerAliasProcessor < Brakeman::AliasProcessor
182
182
  end
183
183
  end
184
184
 
185
- render_path = Brakeman::RenderPath.new.add_controller_render(@current_class, @current_method, line, relative_path(@file))
185
+ render_path = Brakeman::RenderPath.new.add_controller_render(@current_class, @current_method, line, relative_path(@file_name))
186
186
  super name, args, render_path, line
187
187
  end
188
188
 
@@ -88,7 +88,7 @@ class Brakeman::HamlTemplateProcessor < Brakeman::TemplateProcessor
88
88
  #Process call to render()
89
89
  exp.arglist = process exp.arglist
90
90
  make_render_in_view exp
91
- elsif target == nil and method == :find_and_preserve
91
+ elsif target == nil and method == :find_and_preserve and exp.first_arg
92
92
  process exp.first_arg
93
93
  elsif method == :render_with_options
94
94
  if target == JAVASCRIPT_FILTER or target == COFFEE_FILTER
@@ -30,4 +30,22 @@ class Brakeman::BasicProcessor < Brakeman::SexpProcessor
30
30
  process_default exp
31
31
  end
32
32
  end
33
+
34
+ def process_if exp
35
+ condition = exp.condition
36
+
37
+ process condition
38
+
39
+ if true? condition
40
+ process exp.then_clause
41
+ elsif false? condition
42
+ process exp.else_clause
43
+ else
44
+ [exp.then_clause, exp.else_clause].compact.map do |e|
45
+ process e
46
+ end
47
+ end
48
+
49
+ exp
50
+ end
33
51
  end
@@ -27,8 +27,9 @@ class Brakeman::Rails2ConfigProcessor < Brakeman::BasicProcessor
27
27
  end
28
28
 
29
29
  #Use this method to process configuration file
30
- def process_config src
31
- res = Brakeman::ConfigAliasProcessor.new.process_safely(src)
30
+ def process_config src, file_name
31
+ @file_name = file_name
32
+ res = Brakeman::ConfigAliasProcessor.new.process_safely(src, nil, file_name)
32
33
  process res
33
34
  end
34
35
 
@@ -16,6 +16,7 @@ class Brakeman::Rails2RoutesProcessor < Brakeman::BasicProcessor
16
16
  @prefix = [] #Controller name prefix (a module name, usually)
17
17
  @current_controller = nil
18
18
  @with_options = nil #For use inside map.with_options
19
+ @file_name = "config/routes.rb"
19
20
  end
20
21
 
21
22
  #Call this with parsed route file information.
@@ -23,7 +24,7 @@ class Brakeman::Rails2RoutesProcessor < Brakeman::BasicProcessor
23
24
  #This method first calls RouteAliasProcessor#process_safely on the +exp+,
24
25
  #so it does not modify the +exp+.
25
26
  def process_routes exp
26
- process Brakeman::RouteAliasProcessor.new.process_safely(exp)
27
+ process Brakeman::RouteAliasProcessor.new.process_safely(exp, nil, @file_name)
27
28
  end
28
29
 
29
30
  #Looking for mapping of routes
@@ -24,8 +24,9 @@ class Brakeman::Rails3ConfigProcessor < Brakeman::BasicProcessor
24
24
  end
25
25
 
26
26
  #Use this method to process configuration file
27
- def process_config src
28
- res = Brakeman::AliasProcessor.new(@tracker).process_safely(src)
27
+ def process_config src, file_name
28
+ @file_name = file_name
29
+ res = Brakeman::AliasProcessor.new(@tracker).process_safely(src, nil, @file_name)
29
30
  process res
30
31
  end
31
32
 
@@ -17,10 +17,11 @@ class Brakeman::Rails3RoutesProcessor < Brakeman::BasicProcessor
17
17
  @current_controller = nil
18
18
  @with_options = nil #For use inside map.with_options
19
19
  @controller_block = false
20
+ @file_name = "config/routes.rb"
20
21
  end
21
22
 
22
23
  def process_routes exp
23
- process exp.dup
24
+ process Brakeman::AliasProcessor.new.process_safely(exp, nil, @file_name)
24
25
  end
25
26
 
26
27
  def process_call exp
@@ -18,8 +18,8 @@ class Brakeman::TemplateAliasProcessor < Brakeman::AliasProcessor
18
18
  end
19
19
 
20
20
  #Process template
21
- def process_template name, args, _, line = nil
22
- file = relative_path(@template.file || @tracker.templates[@template.name])
21
+ def process_template name, args, _, line = nil, file_name = nil
22
+ @file_name = file_name || relative_path(@template.file || @tracker.templates[@template.name])
23
23
 
24
24
  if @called_from
25
25
  if @called_from.include_template? name
@@ -27,9 +27,9 @@ class Brakeman::TemplateAliasProcessor < Brakeman::AliasProcessor
27
27
  return
28
28
  end
29
29
 
30
- super name, args, @called_from.dup.add_template_render(@template.name, line, file)
30
+ super name, args, @called_from.dup.add_template_render(@template.name, line, @file_name)
31
31
  else
32
- super name, args, Brakeman::RenderPath.new.add_template_render(@template.name, line, file)
32
+ super name, args, Brakeman::RenderPath.new.add_template_render(@template.name, line, @file_name)
33
33
  end
34
34
  end
35
35
 
@@ -8,6 +8,7 @@ class Brakeman::TemplateProcessor < Brakeman::BaseProcessor
8
8
  def initialize tracker, template_name, called_from = nil, file_name = nil
9
9
  super(tracker)
10
10
  @current_template = Brakeman::Template.new template_name, called_from, file_name, tracker
11
+ @file_name = file_name
11
12
 
12
13
  if called_from
13
14
  template_name = (template_name.to_s + "." + called_from.to_s).to_sym
@@ -26,7 +26,8 @@ class Brakeman::Report::CodeClimate < Brakeman::Report::Base
26
26
  location: {
27
27
  path: warning.relative_path,
28
28
  lines: {
29
- begin: warning.line || 1
29
+ begin: warning.line || 1,
30
+ end: warning.line || 1,
30
31
  }
31
32
  },
32
33
  content: {
@@ -116,7 +116,7 @@ class Brakeman::Scanner
116
116
  path = "config/#{file}"
117
117
 
118
118
  if @app_tree.exists?(path)
119
- @processor.process_config(parse_ruby(@app_tree.read(path)))
119
+ @processor.process_config(parse_ruby(@app_tree.read(path)), path)
120
120
  end
121
121
 
122
122
  rescue => e
@@ -5,10 +5,11 @@ require 'brakeman/report'
5
5
  require 'brakeman/processors/lib/find_call'
6
6
  require 'brakeman/processors/lib/find_all_calls'
7
7
  require 'brakeman/tracker/config'
8
+ require 'brakeman/tracker/constants'
8
9
 
9
10
  #The Tracker keeps track of all the processed information.
10
11
  class Brakeman::Tracker
11
- attr_accessor :controllers, :templates, :models, :errors,
12
+ attr_accessor :controllers, :constants, :templates, :models, :errors,
12
13
  :checks, :initializers, :config, :routes, :processor, :libs,
13
14
  :template_cache, :options, :filter_cache, :start_time, :end_time,
14
15
  :duration, :ignored_filter
@@ -38,6 +39,7 @@ class Brakeman::Tracker
38
39
  @initializers = {}
39
40
  @errors = []
40
41
  @libs = {}
42
+ @constants = Brakeman::Constants.new
41
43
  @checks = nil
42
44
  @processed = nil
43
45
  @template_cache = Set.new
@@ -188,6 +190,14 @@ class Brakeman::Tracker
188
190
  end
189
191
  end
190
192
 
193
+ def add_constant name, value, context = nil
194
+ @constants.add name, value, context
195
+ end
196
+
197
+ def constant_lookup name
198
+ @constants.get_literal name
199
+ end
200
+
191
201
  def index_call_sites
192
202
  finder = Brakeman::FindAllCalls.new self
193
203
 
@@ -0,0 +1,101 @@
1
+ require 'brakeman/processors/output_processor'
2
+
3
+ module Brakeman
4
+ class Constant
5
+ attr_reader :name, :file
6
+
7
+ def initialize name, value = nil, context = nil
8
+ set_name name, context
9
+ @values = [ value ]
10
+ @context = context
11
+
12
+ if @context
13
+ @file = @context[:file]
14
+ end
15
+ end
16
+
17
+ def line
18
+ if @values.first.is_a? Sexp
19
+ @values.first.line
20
+ end
21
+ end
22
+
23
+ def set_name name, context
24
+ @name = Constants.constant_as_array(name)
25
+ end
26
+
27
+ def match? name
28
+ @name.reverse.zip(name.reverse).reduce(true) { |m, a| a[1] ? a[0] == a[1] && m : m }
29
+ end
30
+
31
+ def value
32
+ @values.reverse.reduce do |m, v|
33
+ Sexp.new(:or, v, m)
34
+ end
35
+ end
36
+
37
+ def add_value exp
38
+ unless @values.include? exp
39
+ @values << exp
40
+ end
41
+ end
42
+ end
43
+
44
+ class Constants
45
+ include Brakeman::Util
46
+
47
+ def initialize
48
+ @constants = []
49
+ end
50
+
51
+ def [] exp
52
+ return unless constant? exp
53
+ match = find_constant exp
54
+
55
+ if match
56
+ match.value
57
+ else
58
+ nil
59
+ end
60
+ end
61
+
62
+ def find_constant exp
63
+ name = Constants.constant_as_array(exp)
64
+ @constants.find do |c|
65
+ c.match? name
66
+ end
67
+ end
68
+
69
+ def add name, value, context = nil
70
+ if existing = self.find_constant(name)
71
+ existing.add_value value
72
+ else
73
+ @constants << Constant.new(name, value, context)
74
+ end
75
+ end
76
+
77
+ def get_literal name
78
+ if x = self[name] and [:lit, :false, :str, :true, :array, :hash].include? x.node_type
79
+ x
80
+ else
81
+ nil
82
+ end
83
+ end
84
+
85
+ def each &block
86
+ @constants.each &block
87
+ end
88
+
89
+ def self.constant_as_array exp
90
+ get_constant_name(exp).split('::')
91
+ end
92
+
93
+ def self.get_constant_name exp
94
+ if exp.is_a? Sexp
95
+ Brakeman::OutputProcessor.new.format(exp)
96
+ else
97
+ exp.to_s
98
+ end
99
+ end
100
+ end
101
+ end
data/lib/brakeman/util.rb CHANGED
@@ -254,6 +254,10 @@ module Brakeman::Util
254
254
  request_env? exp
255
255
  end
256
256
 
257
+ def constant? exp
258
+ node_type? exp, :const, :colon2, :colon3
259
+ end
260
+
257
261
  #Check if _exp_ is a Sexp.
258
262
  def sexp? exp
259
263
  exp.is_a? Sexp
@@ -1,3 +1,3 @@
1
1
  module Brakeman
2
- Version = "3.2.1"
2
+ Version = "3.3.0"
3
3
  end
@@ -102,6 +102,7 @@ module Brakeman::WarningCodes
102
102
  :CVE_2015_7579 => 98,
103
103
  :dynamic_render_path_rce => 99,
104
104
  :CVE_2015_7581 => 100,
105
+ :secret_in_source => 101,
105
106
  }
106
107
 
107
108
  def self.code name
@@ -326,6 +326,12 @@ class Sexp
326
326
  self[1]
327
327
  end
328
328
 
329
+ def condition= exp
330
+ expect :if
331
+ self[1] = exp
332
+ end
333
+
334
+
329
335
  #Returns 'then' clause of an if expression:
330
336
  #
331
337
  # s(:if,
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brakeman-min
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.1
4
+ version: 3.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Collins
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain:
11
11
  - brakeman-public_cert.pem
12
- date: 2016-02-25 00:00:00.000000000 Z
12
+ date: 2016-05-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: test-unit
@@ -130,6 +130,7 @@ files:
130
130
  - lib/brakeman/checks/check_route_dos.rb
131
131
  - lib/brakeman/checks/check_safe_buffer_manipulation.rb
132
132
  - lib/brakeman/checks/check_sanitize_methods.rb
133
+ - lib/brakeman/checks/check_secrets.rb
133
134
  - lib/brakeman/checks/check_select_tag.rb
134
135
  - lib/brakeman/checks/check_select_vulnerability.rb
135
136
  - lib/brakeman/checks/check_send.rb
@@ -220,6 +221,7 @@ files:
220
221
  - lib/brakeman/tracker.rb
221
222
  - lib/brakeman/tracker/collection.rb
222
223
  - lib/brakeman/tracker/config.rb
224
+ - lib/brakeman/tracker/constants.rb
223
225
  - lib/brakeman/tracker/controller.rb
224
226
  - lib/brakeman/tracker/library.rb
225
227
  - lib/brakeman/tracker/model.rb
@@ -250,7 +252,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
250
252
  version: '0'
251
253
  requirements: []
252
254
  rubyforge_project:
253
- rubygems_version: 2.4.8
255
+ rubygems_version: 2.5.1
254
256
  signing_key:
255
257
  specification_version: 4
256
258
  summary: Security vulnerability scanner for Ruby on Rails.