brakeman-min 3.2.1 → 3.3.0
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.
- checksums.yaml +4 -4
- data/CHANGES +18 -0
- data/bin/brakeman +1 -1
- data/lib/brakeman.rb +9 -1
- data/lib/brakeman/call_index.rb +1 -1
- data/lib/brakeman/checks/check_content_tag.rb +1 -1
- data/lib/brakeman/checks/check_cross_site_scripting.rb +1 -1
- data/lib/brakeman/checks/check_execute.rb +4 -0
- data/lib/brakeman/checks/check_forgery_setting.rb +3 -2
- data/lib/brakeman/checks/check_link_to.rb +1 -1
- data/lib/brakeman/checks/check_link_to_href.rb +2 -2
- data/lib/brakeman/checks/check_mass_assignment.rb +1 -1
- data/lib/brakeman/checks/check_redirect.rb +6 -0
- data/lib/brakeman/checks/check_secrets.rb +40 -0
- data/lib/brakeman/checks/check_sql.rb +1 -1
- data/lib/brakeman/processor.rb +6 -6
- data/lib/brakeman/processors/alias_processor.rb +29 -3
- data/lib/brakeman/processors/base_processor.rb +35 -4
- data/lib/brakeman/processors/controller_alias_processor.rb +4 -4
- data/lib/brakeman/processors/haml_template_processor.rb +1 -1
- data/lib/brakeman/processors/lib/basic_processor.rb +18 -0
- data/lib/brakeman/processors/lib/rails2_config_processor.rb +3 -2
- data/lib/brakeman/processors/lib/rails2_route_processor.rb +2 -1
- data/lib/brakeman/processors/lib/rails3_config_processor.rb +3 -2
- data/lib/brakeman/processors/lib/rails3_route_processor.rb +2 -1
- data/lib/brakeman/processors/template_alias_processor.rb +4 -4
- data/lib/brakeman/processors/template_processor.rb +1 -0
- data/lib/brakeman/report/report_codeclimate.rb +2 -1
- data/lib/brakeman/scanner.rb +1 -1
- data/lib/brakeman/tracker.rb +11 -1
- data/lib/brakeman/tracker/constants.rb +101 -0
- data/lib/brakeman/util.rb +4 -0
- data/lib/brakeman/version.rb +1 -1
- data/lib/brakeman/warning_codes.rb +1 -0
- data/lib/ruby_parser/bm_sexp.rb +6 -0
- metadata +5 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bfbe9bf6ab37921809b33145342e4bcd6df55e8e
|
|
4
|
+
data.tar.gz: 62f41f3c6a63e4f1b9c662b28779cb821d60a7b9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
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 = []
|
data/lib/brakeman/call_index.rb
CHANGED
|
@@ -53,7 +53,7 @@ class Brakeman::CallIndex
|
|
|
53
53
|
elsif method
|
|
54
54
|
calls = calls_by_method method
|
|
55
55
|
else
|
|
56
|
-
|
|
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
|
|
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
|
|
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
|
data/lib/brakeman/processor.rb
CHANGED
|
@@ -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
|
|
92
|
-
res = BaseProcessor.new(@tracker).
|
|
93
|
-
res = AliasProcessor.new(@tracker).
|
|
94
|
-
@tracker.initializers[Pathname.new(
|
|
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
|
-
|
|
48
|
-
|
|
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,
|
|
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
|
-
@
|
|
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
|
-
@
|
|
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(@
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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
|
data/lib/brakeman/scanner.rb
CHANGED
data/lib/brakeman/tracker.rb
CHANGED
|
@@ -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
data/lib/brakeman/version.rb
CHANGED
data/lib/ruby_parser/bm_sexp.rb
CHANGED
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.
|
|
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-
|
|
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.
|
|
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.
|