brakeman-lib 4.5.0 → 4.5.1
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.md +15 -0
- data/README.md +6 -6
- data/lib/brakeman.rb +7 -0
- data/lib/brakeman/app_tree.rb +34 -22
- data/lib/brakeman/checks.rb +7 -7
- data/lib/brakeman/checks/base_check.rb +9 -9
- data/lib/brakeman/checks/check_cross_site_scripting.rb +5 -0
- data/lib/brakeman/checks/check_default_routes.rb +5 -0
- data/lib/brakeman/checks/check_deserialize.rb +52 -0
- data/lib/brakeman/checks/check_dynamic_finders.rb +1 -1
- data/lib/brakeman/checks/check_force_ssl.rb +27 -0
- data/lib/brakeman/checks/check_json_parsing.rb +5 -0
- data/lib/brakeman/checks/check_link_to_href.rb +6 -1
- data/lib/brakeman/checks/check_mail_to.rb +1 -1
- data/lib/brakeman/checks/check_model_attr_accessible.rb +1 -1
- data/lib/brakeman/checks/check_model_attributes.rb +12 -50
- data/lib/brakeman/checks/check_model_serialize.rb +1 -1
- data/lib/brakeman/checks/check_nested_attributes_bypass.rb +3 -3
- data/lib/brakeman/checks/check_secrets.rb +1 -1
- data/lib/brakeman/checks/check_session_settings.rb +10 -10
- data/lib/brakeman/checks/check_simple_format.rb +5 -0
- data/lib/brakeman/checks/check_skip_before_filter.rb +1 -1
- data/lib/brakeman/checks/check_sql.rb +15 -17
- data/lib/brakeman/checks/check_validation_regex.rb +1 -1
- data/lib/brakeman/file_parser.rb +6 -8
- data/lib/brakeman/file_path.rb +71 -0
- data/lib/brakeman/options.rb +7 -0
- data/lib/brakeman/parsers/template_parser.rb +3 -3
- data/lib/brakeman/processor.rb +3 -4
- data/lib/brakeman/processors/alias_processor.rb +12 -6
- data/lib/brakeman/processors/base_processor.rb +8 -7
- data/lib/brakeman/processors/controller_alias_processor.rb +10 -7
- data/lib/brakeman/processors/controller_processor.rb +5 -9
- data/lib/brakeman/processors/haml_template_processor.rb +5 -0
- data/lib/brakeman/processors/lib/module_helper.rb +8 -8
- data/lib/brakeman/processors/lib/processor_helper.rb +3 -3
- data/lib/brakeman/processors/lib/rails2_config_processor.rb +3 -3
- data/lib/brakeman/processors/lib/rails2_route_processor.rb +2 -2
- data/lib/brakeman/processors/lib/rails3_config_processor.rb +3 -3
- data/lib/brakeman/processors/lib/rails3_route_processor.rb +2 -2
- data/lib/brakeman/processors/lib/render_helper.rb +2 -2
- data/lib/brakeman/processors/lib/render_path.rb +18 -1
- data/lib/brakeman/processors/library_processor.rb +5 -5
- data/lib/brakeman/processors/model_processor.rb +4 -5
- data/lib/brakeman/processors/output_processor.rb +5 -0
- data/lib/brakeman/processors/template_alias_processor.rb +4 -5
- data/lib/brakeman/processors/template_processor.rb +4 -4
- data/lib/brakeman/report.rb +3 -3
- data/lib/brakeman/report/ignore/config.rb +2 -3
- data/lib/brakeman/report/ignore/interactive.rb +2 -2
- data/lib/brakeman/report/pager.rb +1 -0
- data/lib/brakeman/report/report_base.rb +51 -6
- data/lib/brakeman/report/report_codeclimate.rb +3 -3
- data/lib/brakeman/report/report_hash.rb +1 -1
- data/lib/brakeman/report/report_html.rb +2 -2
- data/lib/brakeman/report/report_json.rb +1 -24
- data/lib/brakeman/report/report_table.rb +20 -4
- data/lib/brakeman/report/report_tabs.rb +1 -1
- data/lib/brakeman/report/report_text.rb +2 -2
- data/lib/brakeman/rescanner.rb +9 -12
- data/lib/brakeman/scanner.rb +19 -14
- data/lib/brakeman/tracker.rb +4 -4
- data/lib/brakeman/tracker/collection.rb +4 -3
- data/lib/brakeman/tracker/config.rb +6 -0
- data/lib/brakeman/util.rb +1 -147
- data/lib/brakeman/version.rb +1 -1
- data/lib/brakeman/warning.rb +23 -13
- data/lib/brakeman/warning_codes.rb +1 -0
- data/lib/ruby_parser/bm_sexp_processor.rb +1 -0
- metadata +20 -10
@@ -25,7 +25,7 @@ class Brakeman::CheckModelAttrAccessible < Brakeman::BaseCheck
|
|
25
25
|
|
26
26
|
SUSP_ATTRS.each do |susp_attr, confidence|
|
27
27
|
if susp_attr.is_a?(Regexp) and susp_attr =~ attribute.to_s or susp_attr == attribute
|
28
|
-
warn :model =>
|
28
|
+
warn :model => model,
|
29
29
|
:file => model.file,
|
30
30
|
:warning_type => "Mass Assignment",
|
31
31
|
:warning_code => :dangerous_attr_accessible,
|
@@ -2,9 +2,6 @@ require 'brakeman/checks/base_check'
|
|
2
2
|
|
3
3
|
#Check if mass assignment is used with models
|
4
4
|
#which inherit from ActiveRecord::Base.
|
5
|
-
#
|
6
|
-
#If tracker.options[:collapse_mass_assignment] is +true+ (default), all models
|
7
|
-
#which do not use attr_accessible will be reported in a single warning
|
8
5
|
class Brakeman::CheckModelAttributes < Brakeman::BaseCheck
|
9
6
|
Brakeman::Checks.add self
|
10
7
|
|
@@ -15,26 +12,19 @@ class Brakeman::CheckModelAttributes < Brakeman::BaseCheck
|
|
15
12
|
|
16
13
|
#Roll warnings into one warning for all models
|
17
14
|
if tracker.options[:collapse_mass_assignment]
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
check_models do |name, model|
|
22
|
-
if model.attr_protected.nil?
|
23
|
-
no_accessible_names << name.to_s
|
24
|
-
elsif not tracker.options[:ignore_attr_protected]
|
25
|
-
protected_names << name.to_s
|
26
|
-
end
|
27
|
-
end
|
15
|
+
Brakeman.notify "[Notice] The `collapse_mass_assignment` option has been removed."
|
16
|
+
end
|
28
17
|
|
29
|
-
|
30
|
-
|
18
|
+
check_models do |name, model|
|
19
|
+
if model.attr_protected.nil?
|
20
|
+
warn :model => model,
|
21
|
+
:file => model.file,
|
22
|
+
:line => model.top_line,
|
31
23
|
:warning_type => "Attribute Restriction",
|
32
24
|
:warning_code => :no_attr_accessible,
|
33
25
|
:message => msg("Mass assignment is not restricted using ", msg_code("attr_accessible")),
|
34
26
|
:confidence => :high
|
35
|
-
|
36
|
-
|
37
|
-
unless protected_names.empty?
|
27
|
+
elsif not tracker.options[:ignore_attr_protected]
|
38
28
|
message, confidence, link = check_for_attr_protected_bypass
|
39
29
|
|
40
30
|
if link
|
@@ -43,41 +33,13 @@ class Brakeman::CheckModelAttributes < Brakeman::BaseCheck
|
|
43
33
|
warning_code = :attr_protected_used
|
44
34
|
end
|
45
35
|
|
46
|
-
warn :model =>
|
36
|
+
warn :model => model,
|
37
|
+
:file => model.file,
|
38
|
+
:line => model.attr_protected.first.line,
|
47
39
|
:warning_type => "Attribute Restriction",
|
48
40
|
:warning_code => warning_code,
|
49
41
|
:message => message,
|
50
|
-
:confidence => confidence
|
51
|
-
:link => link
|
52
|
-
end
|
53
|
-
else #Output one warning per model
|
54
|
-
|
55
|
-
check_models do |name, model|
|
56
|
-
if model.attr_protected.nil?
|
57
|
-
warn :model => name,
|
58
|
-
:file => model.file,
|
59
|
-
:line => model.top_line,
|
60
|
-
:warning_type => "Attribute Restriction",
|
61
|
-
:warning_code => :no_attr_accessible,
|
62
|
-
:message => msg("Mass assignment is not restricted using ", msg_code("attr_accessible")),
|
63
|
-
:confidence => :high
|
64
|
-
elsif not tracker.options[:ignore_attr_protected]
|
65
|
-
message, confidence, link = check_for_attr_protected_bypass
|
66
|
-
|
67
|
-
if link
|
68
|
-
warning_code = :CVE_2013_0276
|
69
|
-
else
|
70
|
-
warning_code = :attr_protected_used
|
71
|
-
end
|
72
|
-
|
73
|
-
warn :model => name,
|
74
|
-
:file => model.file,
|
75
|
-
:line => model.attr_protected.first.line,
|
76
|
-
:warning_type => "Attribute Restriction",
|
77
|
-
:warning_code => warning_code,
|
78
|
-
:message => message,
|
79
|
-
:confidence => confidence
|
80
|
-
end
|
42
|
+
:confidence => confidence
|
81
43
|
end
|
82
44
|
end
|
83
45
|
end
|
@@ -54,7 +54,7 @@ class Brakeman::CheckModelSerialize < Brakeman::BaseCheck
|
|
54
54
|
confidence = :high
|
55
55
|
end
|
56
56
|
|
57
|
-
warn :model => model
|
57
|
+
warn :model => model,
|
58
58
|
:warning_type => "Remote Code Execution",
|
59
59
|
:warning_code => :CVE_2013_0277,
|
60
60
|
:message => msg("Serialized attributes are vulnerable in ", msg_version(rails_version), ", upgrade to ", msg_version(@upgrade_version), " or patch"),
|
@@ -22,17 +22,17 @@ class Brakeman::CheckNestedAttributesBypass < Brakeman::BaseCheck
|
|
22
22
|
if opts = model.options[:accepts_nested_attributes_for]
|
23
23
|
opts.each do |args|
|
24
24
|
if args.any? { |a| allow_destroy? a } and args.any? { |a| reject_if? a }
|
25
|
-
warn_about_nested_attributes
|
25
|
+
warn_about_nested_attributes model, args
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
def warn_about_nested_attributes
|
32
|
+
def warn_about_nested_attributes model, args
|
33
33
|
message = msg(msg_version(rails_version), " does not call ", msg_code(":reject_if"), " option when ", msg_code(":allow_destroy"), " is ", msg_code("false"), " ", msg_cve("CVE-2015-7577"))
|
34
34
|
|
35
|
-
warn :model =>
|
35
|
+
warn :model => model,
|
36
36
|
:warning_type => "Nested Attributes",
|
37
37
|
:warning_code => :CVE_2015_7577,
|
38
38
|
:message => message,
|
@@ -35,6 +35,6 @@ class Brakeman::CheckSecrets < Brakeman::BaseCheck
|
|
35
35
|
|
36
36
|
def looks_like_secret? name
|
37
37
|
# REST_AUTH_SITE_KEY is the pepper in Devise
|
38
|
-
name.match
|
38
|
+
name.match(/password|secret|(rest_auth_site|api)_key$/i)
|
39
39
|
end
|
40
40
|
end
|
@@ -19,7 +19,7 @@ class Brakeman::CheckSessionSettings < Brakeman::BaseCheck
|
|
19
19
|
def run_check
|
20
20
|
settings = tracker.config.session_settings
|
21
21
|
|
22
|
-
check_for_issues settings, @app_tree.
|
22
|
+
check_for_issues settings, @app_tree.file_path("config/environment.rb")
|
23
23
|
|
24
24
|
["session_store.rb", "secret_token.rb"].each do |file|
|
25
25
|
if tracker.initializers[file] and not ignored? file
|
@@ -42,13 +42,13 @@ class Brakeman::CheckSessionSettings < Brakeman::BaseCheck
|
|
42
42
|
#in Rails 4.x apps
|
43
43
|
def process_attrasgn exp
|
44
44
|
if not tracker.options[:rails3] and exp.target == @session_settings and exp.method == :session=
|
45
|
-
check_for_issues exp.first_arg, @app_tree.
|
45
|
+
check_for_issues exp.first_arg, @app_tree.file_path("config/initializers/session_store.rb")
|
46
46
|
end
|
47
47
|
|
48
48
|
if tracker.options[:rails3] and settings_target?(exp.target) and
|
49
49
|
(exp.method == :secret_token= or exp.method == :secret_key_base=) and string? exp.first_arg
|
50
50
|
|
51
|
-
warn_about_secret_token exp.line, @app_tree.
|
51
|
+
warn_about_secret_token exp.line, @app_tree.file_path("config/initializers/secret_token.rb")
|
52
52
|
end
|
53
53
|
|
54
54
|
exp
|
@@ -58,7 +58,7 @@ class Brakeman::CheckSessionSettings < Brakeman::BaseCheck
|
|
58
58
|
#in Rails 3.x apps
|
59
59
|
def process_call exp
|
60
60
|
if tracker.options[:rails3] and settings_target?(exp.target) and exp.method == :session_store
|
61
|
-
check_for_rails3_issues exp.second_arg, @app_tree.
|
61
|
+
check_for_rails3_issues exp.second_arg, @app_tree.file_path("config/initializers/session_store.rb")
|
62
62
|
end
|
63
63
|
|
64
64
|
exp
|
@@ -109,10 +109,10 @@ class Brakeman::CheckSessionSettings < Brakeman::BaseCheck
|
|
109
109
|
end
|
110
110
|
|
111
111
|
def check_secrets_yaml
|
112
|
-
secrets_file = "config/secrets.yml"
|
112
|
+
secrets_file = @app_tree.file_path("config/secrets.yml")
|
113
113
|
|
114
|
-
if
|
115
|
-
yaml =
|
114
|
+
if secrets_file.exists? and not ignored? "secrets.yml" and not ignored? "config/*.yml"
|
115
|
+
yaml = secrets_file.read
|
116
116
|
require 'date' # https://github.com/dtao/safe_yaml/issues/80
|
117
117
|
require 'safe_yaml/load'
|
118
118
|
begin
|
@@ -127,7 +127,7 @@ class Brakeman::CheckSessionSettings < Brakeman::BaseCheck
|
|
127
127
|
unless secret.include? "<%="
|
128
128
|
line = yaml.lines.find_index { |l| l.include? secret } + 1
|
129
129
|
|
130
|
-
warn_about_secret_token line, @app_tree.
|
130
|
+
warn_about_secret_token line, @app_tree.file_path(secrets_file)
|
131
131
|
end
|
132
132
|
end
|
133
133
|
end
|
@@ -163,9 +163,9 @@ class Brakeman::CheckSessionSettings < Brakeman::BaseCheck
|
|
163
163
|
|
164
164
|
def ignored? file
|
165
165
|
[".", "config", "config/initializers"].each do |dir|
|
166
|
-
ignore_file = "#{dir}/.gitignore"
|
166
|
+
ignore_file = @app_tree.file_path("#{dir}/.gitignore")
|
167
167
|
if @app_tree.exists? ignore_file
|
168
|
-
input =
|
168
|
+
input = ignore_file.read
|
169
169
|
|
170
170
|
return true if input.include? file
|
171
171
|
end
|
@@ -5,6 +5,11 @@ class Brakeman::CheckSimpleFormat < Brakeman::CheckCrossSiteScripting
|
|
5
5
|
|
6
6
|
@description = "Checks for simple_format XSS vulnerability (CVE-2013-6416) in certain versions"
|
7
7
|
|
8
|
+
def initialize *args
|
9
|
+
super
|
10
|
+
@found_any = false
|
11
|
+
end
|
12
|
+
|
8
13
|
def run_check
|
9
14
|
if version_between? "4.0.0", "4.0.1"
|
10
15
|
@inspect_arguments = true
|
@@ -38,7 +38,7 @@ class Brakeman::CheckSkipBeforeFilter < Brakeman::BaseCheck
|
|
38
38
|
:message => msg("Use whitelist (", msg_code(":only => [..]"), ") when skipping authentication"),
|
39
39
|
:code => filter,
|
40
40
|
:confidence => :medium,
|
41
|
-
:
|
41
|
+
:link_path => "authentication_whitelist",
|
42
42
|
:file => controller.file
|
43
43
|
end
|
44
44
|
end
|
@@ -21,7 +21,8 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
|
|
21
21
|
@sql_targets = [:average, :calculate, :count, :count_by_sql, :delete_all, :destroy_all,
|
22
22
|
:find_by_sql, :maximum, :minimum, :pluck, :sum, :update_all]
|
23
23
|
@sql_targets.concat [:from, :group, :having, :joins, :lock, :order, :reorder, :where] if tracker.options[:rails3]
|
24
|
-
@sql_targets
|
24
|
+
@sql_targets.concat [:find_by, :find_by!, :find_or_create_by, :find_or_create_by!, :find_or_initialize_by, :not] if tracker.options[:rails4]
|
25
|
+
@sql_targets << :delete_by << :destroy_by if tracker.options[:rails6]
|
25
26
|
|
26
27
|
if version_between?("2.0.0", "3.9.9") or tracker.config.rails_version.nil?
|
27
28
|
@sql_targets << :first << :last << :all
|
@@ -71,23 +72,23 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
|
|
71
72
|
scope_calls = []
|
72
73
|
|
73
74
|
if version_between?("2.1.0", "3.0.9")
|
74
|
-
ar_scope_calls(:named_scope) do |
|
75
|
+
ar_scope_calls(:named_scope) do |model, args|
|
75
76
|
call = make_call(nil, :named_scope, args).line(args.line)
|
76
|
-
scope_calls << scope_call_hash(call,
|
77
|
+
scope_calls << scope_call_hash(call, model, :named_scope)
|
77
78
|
end
|
78
79
|
elsif version_between?("3.1.0", "9.9.9")
|
79
|
-
ar_scope_calls(:scope) do |
|
80
|
+
ar_scope_calls(:scope) do |model, args|
|
80
81
|
second_arg = args[2]
|
81
82
|
next unless sexp? second_arg
|
82
83
|
|
83
84
|
if second_arg.node_type == :iter and node_type? second_arg.block, :block, :call, :safe_call
|
84
|
-
process_scope_with_block(
|
85
|
+
process_scope_with_block(model, args)
|
85
86
|
elsif call? second_arg
|
86
87
|
call = second_arg
|
87
|
-
scope_calls << scope_call_hash(call,
|
88
|
+
scope_calls << scope_call_hash(call, model, call.method)
|
88
89
|
else
|
89
90
|
call = make_call(nil, :scope, args).line(args.line)
|
90
|
-
scope_calls << scope_call_hash(call,
|
91
|
+
scope_calls << scope_call_hash(call, model, :scope)
|
91
92
|
end
|
92
93
|
end
|
93
94
|
end
|
@@ -96,37 +97,34 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
|
|
96
97
|
end
|
97
98
|
|
98
99
|
def ar_scope_calls(symbol_name = :named_scope, &block)
|
99
|
-
return_array = []
|
100
100
|
active_record_models.each do |name, model|
|
101
101
|
model_args = model.options[symbol_name]
|
102
102
|
if model_args
|
103
103
|
model_args.each do |args|
|
104
|
-
yield
|
105
|
-
return_array << [name, args]
|
104
|
+
yield model, args
|
106
105
|
end
|
107
106
|
end
|
108
107
|
end
|
109
|
-
return_array
|
110
108
|
end
|
111
109
|
|
112
|
-
def scope_call_hash(call,
|
113
|
-
{ :call => call, :location => { :type => :class, :class => name }, :method => :named_scope }
|
110
|
+
def scope_call_hash(call, model, method)
|
111
|
+
{ :call => call, :location => { :type => :class, :class => model.name, :file => model.file }, :method => :named_scope }
|
114
112
|
end
|
115
113
|
|
116
114
|
|
117
|
-
def process_scope_with_block
|
115
|
+
def process_scope_with_block model, args
|
118
116
|
scope_name = args[1][1]
|
119
117
|
block = args[-1][-1]
|
120
118
|
|
121
119
|
# Search lambda for calls to query methods
|
122
120
|
if block.node_type == :block
|
123
121
|
find_calls = Brakeman::FindAllCalls.new(tracker)
|
124
|
-
find_calls.process_source(block, :class =>
|
122
|
+
find_calls.process_source(block, :class => model.name, :method => scope_name, :file => model.file)
|
125
123
|
find_calls.calls.each { |call| process_result(call) if @sql_targets.include?(call[:method]) }
|
126
124
|
elsif call? block
|
127
125
|
while call? block
|
128
126
|
process_result :target => block.target, :method => block.method, :call => block,
|
129
|
-
|
127
|
+
:location => { :type => :class, :class => model.name, :method => scope_name, :file => model.file }
|
130
128
|
|
131
129
|
block = block.target
|
132
130
|
end
|
@@ -187,7 +185,7 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
|
|
187
185
|
else
|
188
186
|
check_find_arguments call.last_arg
|
189
187
|
end
|
190
|
-
when :where, :having, :find_by, :find_by!, :not
|
188
|
+
when :where, :having, :find_by, :find_by!, :find_or_create_by, :find_or_create_by!, :find_or_initialize_by,:not, :delete_by, :destroy_by
|
191
189
|
check_query_arguments call.arglist
|
192
190
|
when :order, :group, :reorder
|
193
191
|
check_order_arguments call.arglist
|
@@ -17,7 +17,7 @@ class Brakeman::CheckValidationRegex < Brakeman::BaseCheck
|
|
17
17
|
|
18
18
|
def run_check
|
19
19
|
active_record_models.each do |name, model|
|
20
|
-
@current_model =
|
20
|
+
@current_model = model
|
21
21
|
format_validations = model.options[:validates_format_of]
|
22
22
|
|
23
23
|
if format_validations
|
data/lib/brakeman/file_parser.rb
CHANGED
@@ -5,16 +5,16 @@ module Brakeman
|
|
5
5
|
class FileParser
|
6
6
|
attr_reader :file_list
|
7
7
|
|
8
|
-
def initialize tracker
|
8
|
+
def initialize tracker
|
9
9
|
@tracker = tracker
|
10
10
|
@timeout = @tracker.options[:parser_timeout]
|
11
|
-
@app_tree = app_tree
|
11
|
+
@app_tree = @tracker.app_tree
|
12
12
|
@file_list = {}
|
13
13
|
end
|
14
14
|
|
15
15
|
def parse_files list, type
|
16
16
|
read_files list, type do |path, contents|
|
17
|
-
if ast = parse_ruby(contents, path)
|
17
|
+
if ast = parse_ruby(contents, path.relative)
|
18
18
|
ASTFile.new(path, ast)
|
19
19
|
end
|
20
20
|
end
|
@@ -24,7 +24,9 @@ module Brakeman
|
|
24
24
|
@file_list[type] ||= []
|
25
25
|
|
26
26
|
list.each do |path|
|
27
|
-
|
27
|
+
file = @app_tree.file_path(path)
|
28
|
+
|
29
|
+
result = yield file, file.read
|
28
30
|
if result
|
29
31
|
@file_list[type] << result
|
30
32
|
end
|
@@ -50,9 +52,5 @@ module Brakeman
|
|
50
52
|
nil
|
51
53
|
end
|
52
54
|
end
|
53
|
-
|
54
|
-
def read_path path
|
55
|
-
@app_tree.read_path path
|
56
|
-
end
|
57
55
|
end
|
58
56
|
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
module Brakeman
|
4
|
+
# Class to represent file paths within Brakeman.
|
5
|
+
# FilePath objects track both the relative and absolute paths
|
6
|
+
# to make it easier to manage paths.
|
7
|
+
class FilePath
|
8
|
+
attr_reader :absolute, :relative
|
9
|
+
@cache = {}
|
10
|
+
|
11
|
+
# Create a new FilePath using an AppTree object.
|
12
|
+
#
|
13
|
+
# Note that if the path is already a FilePath, that path will
|
14
|
+
# be returned unaltered.
|
15
|
+
#
|
16
|
+
# Additionally, paths are cached. If the absolute path already has
|
17
|
+
# a FilePath in the cache, that existing FilePath will be returned.
|
18
|
+
def self.from_app_tree app_tree, path
|
19
|
+
return path if path.is_a? Brakeman::FilePath
|
20
|
+
|
21
|
+
absolute = app_tree.expand_path(path).freeze
|
22
|
+
|
23
|
+
if fp = @cache[absolute]
|
24
|
+
return fp
|
25
|
+
end
|
26
|
+
|
27
|
+
relative = app_tree.relative_path(path).freeze
|
28
|
+
|
29
|
+
self.new(absolute, relative).tap { |fp| @cache[absolute] = fp }
|
30
|
+
end
|
31
|
+
|
32
|
+
# Create a new FilePath with the given absolute and relative paths.
|
33
|
+
def initialize absolute_path, relative_path
|
34
|
+
@absolute = absolute_path
|
35
|
+
@relative = relative_path
|
36
|
+
end
|
37
|
+
|
38
|
+
# Read file from absolute path.
|
39
|
+
def read
|
40
|
+
File.read self.absolute
|
41
|
+
end
|
42
|
+
|
43
|
+
# Check if absolute path exists.
|
44
|
+
def exists?
|
45
|
+
File.exist? self.absolute
|
46
|
+
end
|
47
|
+
|
48
|
+
# Compare FilePaths. Raises an ArgumentError unless both objects are FilePaths.
|
49
|
+
def <=> rhs
|
50
|
+
raise ArgumentError unless rhs.is_a? Brakeman::FilePath
|
51
|
+
self.relative <=> rhs.relative
|
52
|
+
end
|
53
|
+
|
54
|
+
# Compare FilePaths. Raises an ArgumentError unless both objects are FilePaths.
|
55
|
+
def == rhs
|
56
|
+
return false unless rhs.is_a? Brakeman::FilePath
|
57
|
+
|
58
|
+
self.absolute == rhs.absolute
|
59
|
+
end
|
60
|
+
|
61
|
+
# Returns a string with the absolute path.
|
62
|
+
def to_str
|
63
|
+
self.absolute
|
64
|
+
end
|
65
|
+
|
66
|
+
# Returns a string with the absolute path.
|
67
|
+
def to_s
|
68
|
+
self.to_str
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/brakeman/options.rb
CHANGED
@@ -82,6 +82,13 @@ module Brakeman::Options
|
|
82
82
|
options[:rails5] = true
|
83
83
|
end
|
84
84
|
|
85
|
+
opts.on "-6", "--rails6", "Force Rails 6 mode" do
|
86
|
+
options[:rails3] = true
|
87
|
+
options[:rails4] = true
|
88
|
+
options[:rails5] = true
|
89
|
+
options[:rails6] = true
|
90
|
+
end
|
91
|
+
|
85
92
|
opts.separator ""
|
86
93
|
opts.separator "Scanning options:"
|
87
94
|
|