brakeman-lib 4.4.0 → 4.7.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.md +63 -0
- data/README.md +6 -7
- data/lib/brakeman.rb +7 -0
- data/lib/brakeman/app_tree.rb +34 -22
- data/lib/brakeman/call_index.rb +54 -15
- data/lib/brakeman/checks.rb +7 -7
- data/lib/brakeman/checks/base_check.rb +75 -56
- data/lib/brakeman/checks/check_content_tag.rb +12 -0
- data/lib/brakeman/checks/check_cookie_serialization.rb +22 -0
- data/lib/brakeman/checks/check_cross_site_scripting.rb +15 -10
- data/lib/brakeman/checks/check_default_routes.rb +5 -0
- data/lib/brakeman/checks/check_deserialize.rb +49 -0
- data/lib/brakeman/checks/check_dynamic_finders.rb +1 -1
- data/lib/brakeman/checks/check_evaluation.rb +0 -1
- data/lib/brakeman/checks/check_execute.rb +44 -1
- data/lib/brakeman/checks/check_file_access.rb +7 -1
- data/lib/brakeman/checks/check_force_ssl.rb +27 -0
- data/lib/brakeman/checks/check_header_dos.rb +2 -2
- data/lib/brakeman/checks/check_i18n_xss.rb +2 -2
- data/lib/brakeman/checks/check_jruby_xml.rb +2 -2
- data/lib/brakeman/checks/check_json_parsing.rb +7 -2
- 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_mime_type_dos.rb +2 -2
- 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 +4 -4
- data/lib/brakeman/checks/check_reverse_tabnabbing.rb +54 -0
- data/lib/brakeman/checks/check_sanitize_methods.rb +2 -2
- data/lib/brakeman/checks/check_secrets.rb +1 -1
- data/lib/brakeman/checks/check_send.rb +0 -1
- data/lib/brakeman/checks/check_session_manipulation.rb +0 -1
- data/lib/brakeman/checks/check_session_settings.rb +15 -12
- 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 +27 -20
- data/lib/brakeman/checks/check_validation_regex.rb +1 -1
- data/lib/brakeman/checks/check_xml_dos.rb +2 -2
- data/lib/brakeman/checks/check_yaml_parsing.rb +10 -18
- data/lib/brakeman/differ.rb +16 -28
- data/lib/brakeman/file_parser.rb +6 -8
- data/lib/brakeman/file_path.rb +85 -0
- data/lib/brakeman/options.rb +7 -0
- data/lib/brakeman/parsers/haml_embedded.rb +44 -0
- data/lib/brakeman/parsers/slim_embedded.rb +44 -0
- data/lib/brakeman/parsers/template_parser.rb +8 -8
- data/lib/brakeman/processor.rb +4 -5
- data/lib/brakeman/processors/alias_processor.rb +49 -7
- data/lib/brakeman/processors/base_processor.rb +10 -7
- data/lib/brakeman/processors/controller_alias_processor.rb +10 -7
- data/lib/brakeman/processors/controller_processor.rb +9 -13
- data/lib/brakeman/processors/gem_processor.rb +10 -2
- data/lib/brakeman/processors/haml_template_processor.rb +92 -123
- data/lib/brakeman/processors/lib/call_conversion_helper.rb +4 -0
- data/lib/brakeman/processors/lib/find_all_calls.rb +27 -4
- data/lib/brakeman/processors/lib/find_call.rb +3 -64
- 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 +4 -4
- 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/slim_template_processor.rb +16 -0
- data/lib/brakeman/processors/template_alias_processor.rb +32 -5
- data/lib/brakeman/processors/template_processor.rb +14 -10
- 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 +13 -12
- data/lib/brakeman/scanner.rb +24 -18
- data/lib/brakeman/tracker.rb +35 -7
- data/lib/brakeman/tracker/collection.rb +4 -3
- data/lib/brakeman/tracker/config.rb +44 -48
- data/lib/brakeman/tracker/constants.rb +2 -1
- data/lib/brakeman/util.rb +18 -147
- data/lib/brakeman/version.rb +1 -1
- data/lib/brakeman/warning.rb +27 -13
- data/lib/brakeman/warning_codes.rb +4 -0
- data/lib/ruby_parser/bm_sexp.rb +1 -1
- data/lib/ruby_parser/bm_sexp_processor.rb +1 -0
- metadata +58 -43
data/lib/brakeman/scanner.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
begin
|
2
2
|
Brakeman.load_brakeman_dependency 'ruby_parser'
|
3
|
+
Brakeman.load_brakeman_dependency 'ruby_parser/legacy'
|
3
4
|
require 'ruby_parser/bm_sexp.rb'
|
4
5
|
require 'ruby_parser/bm_sexp_processor.rb'
|
5
6
|
require 'brakeman/processor'
|
@@ -15,7 +16,6 @@ end
|
|
15
16
|
#Scans the Rails application.
|
16
17
|
class Brakeman::Scanner
|
17
18
|
attr_reader :options
|
18
|
-
RUBY_1_9 = RUBY_VERSION >= "1.9.0"
|
19
19
|
|
20
20
|
#Pass in path to the root of the Rails application
|
21
21
|
def initialize options, processor = nil
|
@@ -65,7 +65,7 @@ class Brakeman::Scanner
|
|
65
65
|
end
|
66
66
|
|
67
67
|
def parse_files
|
68
|
-
fp = Brakeman::FileParser.new tracker
|
68
|
+
fp = Brakeman::FileParser.new tracker
|
69
69
|
|
70
70
|
files = {
|
71
71
|
:initializers => @app_tree.initializer_paths,
|
@@ -94,7 +94,7 @@ class Brakeman::Scanner
|
|
94
94
|
#
|
95
95
|
#Stores parsed information in tracker.config
|
96
96
|
def process_config
|
97
|
-
if options[:rails3] or options[:rails4] or options[:rails5]
|
97
|
+
if options[:rails3] or options[:rails4] or options[:rails5] or options[:rails6]
|
98
98
|
process_config_file "application.rb"
|
99
99
|
process_config_file "environments/production.rb"
|
100
100
|
else
|
@@ -110,15 +110,15 @@ class Brakeman::Scanner
|
|
110
110
|
end
|
111
111
|
|
112
112
|
if @app_tree.exists? ".ruby-version"
|
113
|
-
tracker.config.set_ruby_version @app_tree.
|
113
|
+
tracker.config.set_ruby_version @app_tree.file_path(".ruby-version").read
|
114
114
|
end
|
115
115
|
end
|
116
116
|
|
117
117
|
def process_config_file file
|
118
|
-
path = "config/#{file}"
|
118
|
+
path = @app_tree.file_path("config/#{file}")
|
119
119
|
|
120
|
-
if
|
121
|
-
@processor.process_config(
|
120
|
+
if path.exists?
|
121
|
+
@processor.process_config(parse_ruby_file(path), path)
|
122
122
|
end
|
123
123
|
|
124
124
|
rescue => e
|
@@ -131,20 +131,25 @@ class Brakeman::Scanner
|
|
131
131
|
#Process Gemfile
|
132
132
|
def process_gems
|
133
133
|
gem_files = {}
|
134
|
+
|
134
135
|
if @app_tree.exists? "Gemfile"
|
135
|
-
|
136
|
+
file = @app_tree.file_path("Gemfile")
|
137
|
+
gem_files[:gemfile] = { :src => parse_ruby_file(file), :file => file }
|
136
138
|
elsif @app_tree.exists? "gems.rb"
|
137
|
-
|
139
|
+
file = @app_tree.file_path("gems.rb")
|
140
|
+
gem_files[:gemfile] = { :src => parse_ruby_file(file), :file => file }
|
138
141
|
end
|
139
142
|
|
140
143
|
if @app_tree.exists? "Gemfile.lock"
|
141
|
-
|
144
|
+
file = @app_tree.file_path("Gemfile.lock")
|
145
|
+
gem_files[:gemlock] = { :src => file.read, :file => file }
|
142
146
|
elsif @app_tree.exists? "gems.locked"
|
143
|
-
|
147
|
+
file = @app_tree.file_path("gems.locked")
|
148
|
+
gem_files[:gemlock] = { :src => file.read, :file => file }
|
144
149
|
end
|
145
150
|
|
146
151
|
if @app_tree.gemspec
|
147
|
-
gem_files[:gemspec] = { :src =>
|
152
|
+
gem_files[:gemspec] = { :src => parse_ruby_file(@app_tree.gemspec), :file => @app_tree.gemspec }
|
148
153
|
end
|
149
154
|
|
150
155
|
if not gem_files.empty?
|
@@ -214,10 +219,10 @@ class Brakeman::Scanner
|
|
214
219
|
#Adds parsed information to tracker.routes
|
215
220
|
def process_routes
|
216
221
|
if @app_tree.exists?("config/routes.rb")
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
222
|
+
file = @app_tree.file_path("config/routes.rb")
|
223
|
+
if routes_sexp = parse_ruby_file(file)
|
224
|
+
@processor.process_routes routes_sexp
|
225
|
+
else
|
221
226
|
Brakeman.notify "[Notice] Error while processing routes - assuming all public controller methods are actions."
|
222
227
|
options[:assume_all_routes] = true
|
223
228
|
end
|
@@ -316,8 +321,9 @@ class Brakeman::Scanner
|
|
316
321
|
tracker.index_call_sites
|
317
322
|
end
|
318
323
|
|
319
|
-
def
|
320
|
-
|
324
|
+
def parse_ruby_file file
|
325
|
+
fp = Brakeman::FileParser.new(self.tracker)
|
326
|
+
fp.parse_ruby(file.read, file)
|
321
327
|
end
|
322
328
|
end
|
323
329
|
|
data/lib/brakeman/tracker.rb
CHANGED
@@ -12,7 +12,7 @@ class Brakeman::Tracker
|
|
12
12
|
attr_accessor :controllers, :constants, :templates, :models, :errors,
|
13
13
|
:checks, :initializers, :config, :routes, :processor, :libs,
|
14
14
|
:template_cache, :options, :filter_cache, :start_time, :end_time,
|
15
|
-
:duration, :ignored_filter
|
15
|
+
:duration, :ignored_filter, :app_tree
|
16
16
|
|
17
17
|
#Place holder when there should be a model, but it is not
|
18
18
|
#clear what model it will be.
|
@@ -34,7 +34,7 @@ class Brakeman::Tracker
|
|
34
34
|
#we can match models later without knowing precisely what
|
35
35
|
#class they are.
|
36
36
|
@models = {}
|
37
|
-
@models[UNKNOWN_MODEL] = Brakeman::Model.new(UNKNOWN_MODEL, nil,
|
37
|
+
@models[UNKNOWN_MODEL] = Brakeman::Model.new(UNKNOWN_MODEL, nil, @app_tree.file_path("NOT_REAL.rb"), nil, self)
|
38
38
|
@routes = {}
|
39
39
|
@initializers = {}
|
40
40
|
@errors = []
|
@@ -61,13 +61,17 @@ class Brakeman::Tracker
|
|
61
61
|
Brakeman.debug exception
|
62
62
|
Brakeman.debug backtrace
|
63
63
|
|
64
|
-
@errors << {
|
64
|
+
@errors << {
|
65
|
+
:exception => exception,
|
66
|
+
:error => exception.to_s.gsub("\n", " "),
|
67
|
+
:backtrace => backtrace
|
68
|
+
}
|
65
69
|
end
|
66
70
|
|
67
71
|
#Run a set of checks on the current information. Results will be stored
|
68
72
|
#in Tracker#checks.
|
69
73
|
def run_checks
|
70
|
-
@checks = Brakeman::Checks.run_checks(
|
74
|
+
@checks = Brakeman::Checks.run_checks(self)
|
71
75
|
|
72
76
|
@end_time = Time.now
|
73
77
|
@duration = @end_time - @start_time
|
@@ -168,7 +172,7 @@ class Brakeman::Tracker
|
|
168
172
|
|
169
173
|
#Returns a Report with this Tracker's information
|
170
174
|
def report
|
171
|
-
Brakeman::Report.new(
|
175
|
+
Brakeman::Report.new(self)
|
172
176
|
end
|
173
177
|
|
174
178
|
def warnings
|
@@ -223,6 +227,10 @@ class Brakeman::Tracker
|
|
223
227
|
finder.process_source template.src, :template => template, :file => template.file
|
224
228
|
end
|
225
229
|
|
230
|
+
self.initializers.each do |file_name, src|
|
231
|
+
finder.process_all_source src, :file => file_name
|
232
|
+
end
|
233
|
+
|
226
234
|
@call_index = Brakeman::CallIndex.new finder.calls
|
227
235
|
end
|
228
236
|
|
@@ -233,8 +241,8 @@ class Brakeman::Tracker
|
|
233
241
|
#
|
234
242
|
#This will limit reindexing to the given sets
|
235
243
|
def reindex_call_sites locations
|
236
|
-
#If reindexing templates, models,
|
237
|
-
#everything
|
244
|
+
#If reindexing templates, models, controllers,
|
245
|
+
#just redo everything.
|
238
246
|
if locations.length == 3
|
239
247
|
return index_call_sites
|
240
248
|
end
|
@@ -256,6 +264,12 @@ class Brakeman::Tracker
|
|
256
264
|
method_sets << self.controllers
|
257
265
|
end
|
258
266
|
|
267
|
+
if locations.include? :initializers
|
268
|
+
self.initializers.each do |file_name, src|
|
269
|
+
@call_index.remove_indexes_by_file file_name
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
259
273
|
@call_index.remove_indexes_by_class classes_to_reindex
|
260
274
|
|
261
275
|
finder = Brakeman::FindAllCalls.new self
|
@@ -275,6 +289,12 @@ class Brakeman::Tracker
|
|
275
289
|
end
|
276
290
|
end
|
277
291
|
|
292
|
+
if locations.include? :initializers
|
293
|
+
self.initializers.each do |file_name, src|
|
294
|
+
finder.process_all_source src, :file => file_name
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
278
298
|
@call_index.index_calls finder.calls
|
279
299
|
end
|
280
300
|
|
@@ -359,4 +379,12 @@ class Brakeman::Tracker
|
|
359
379
|
def reset_routes
|
360
380
|
@routes = {}
|
361
381
|
end
|
382
|
+
|
383
|
+
def reset_initializer path
|
384
|
+
@initializers.delete_if do |file, src|
|
385
|
+
path.relative.include? file
|
386
|
+
end
|
387
|
+
|
388
|
+
@call_index.remove_indexes_by_file path
|
389
|
+
end
|
362
390
|
end
|
@@ -9,13 +9,14 @@ module Brakeman
|
|
9
9
|
def initialize name, parent, file_name, src, tracker
|
10
10
|
@name = name
|
11
11
|
@parent = parent
|
12
|
-
@
|
13
|
-
@
|
14
|
-
@src = { file_name => src }
|
12
|
+
@files = []
|
13
|
+
@src = {}
|
15
14
|
@includes = []
|
16
15
|
@methods = { :public => {}, :private => {}, :protected => {} }
|
17
16
|
@options = {}
|
18
17
|
@tracker = tracker
|
18
|
+
|
19
|
+
add_file file_name, src
|
19
20
|
end
|
20
21
|
|
21
22
|
def ancestor? parent, seen={}
|
@@ -4,10 +4,8 @@ module Brakeman
|
|
4
4
|
class Config
|
5
5
|
include Util
|
6
6
|
|
7
|
-
attr_reader :rails, :tracker
|
8
|
-
attr_accessor :rails_version, :ruby_version
|
7
|
+
attr_reader :gems, :rails, :ruby_version, :tracker
|
9
8
|
attr_writer :erubis, :escape_html
|
10
|
-
attr_reader :gems
|
11
9
|
|
12
10
|
def initialize tracker
|
13
11
|
@tracker = tracker
|
@@ -19,16 +17,9 @@ module Brakeman
|
|
19
17
|
@ruby_version = ""
|
20
18
|
end
|
21
19
|
|
22
|
-
def allow_forgery_protection?
|
23
|
-
@rails[:action_controller] and
|
24
|
-
@rails[:action_controller][:allow_forgery_protection] == Sexp.new(:false)
|
25
|
-
end
|
26
|
-
|
27
20
|
def default_protect_from_forgery?
|
28
|
-
if version_between? "5.2.0", "9.9.9"
|
29
|
-
if @rails
|
30
|
-
@rails[:action_controller][:default_protect_from_forgery] == Sexp.new(:false)
|
31
|
-
|
21
|
+
if version_between? "5.2.0.beta1", "9.9.9"
|
22
|
+
if @rails.dig(:action_controller, :default_protect_from_forgery) == Sexp.new(:false)
|
32
23
|
return false
|
33
24
|
else
|
34
25
|
return true
|
@@ -48,17 +39,21 @@ module Brakeman
|
|
48
39
|
|
49
40
|
def escape_html_entities_in_json?
|
50
41
|
#TODO add version-specific information here
|
51
|
-
@rails
|
52
|
-
|
42
|
+
true? @rails.dig(:active_support, :escape_html_entities_in_json)
|
43
|
+
end
|
44
|
+
|
45
|
+
def escape_filter_interpolations?
|
46
|
+
# TODO see if app is actually turning this off itself
|
47
|
+
has_gem?(:haml) and
|
48
|
+
version_between? "5.0.0", "5.99", gem_version(:haml)
|
53
49
|
end
|
54
50
|
|
55
51
|
def whitelist_attributes?
|
56
|
-
@rails
|
57
|
-
@rails[:active_record][:whitelist_attributes] == Sexp.new(:true)
|
52
|
+
@rails.dig(:active_record, :whitelist_attributes) == Sexp.new(:true)
|
58
53
|
end
|
59
54
|
|
60
55
|
def gem_version name
|
61
|
-
@gems
|
56
|
+
extract_version @gems.dig(name, :version)
|
62
57
|
end
|
63
58
|
|
64
59
|
def add_gem name, version, file, line
|
@@ -78,11 +73,16 @@ module Brakeman
|
|
78
73
|
@gems[name]
|
79
74
|
end
|
80
75
|
|
81
|
-
def set_rails_version
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
76
|
+
def set_rails_version version = nil
|
77
|
+
version = if version
|
78
|
+
# Only used by Rails2ConfigProcessor right now
|
79
|
+
extract_version(version)
|
80
|
+
else
|
81
|
+
gem_version(:rails) || gem_version(:railties)
|
82
|
+
end
|
83
|
+
|
84
|
+
if version
|
85
|
+
@rails_version = version
|
86
86
|
|
87
87
|
if tracker.options[:rails3].nil? and tracker.options[:rails4].nil?
|
88
88
|
if @rails_version.start_with? "3"
|
@@ -97,6 +97,12 @@ module Brakeman
|
|
97
97
|
tracker.options[:rails4] = true
|
98
98
|
tracker.options[:rails5] = true
|
99
99
|
Brakeman.notify "[Notice] Detected Rails 5 application"
|
100
|
+
elsif @rails_version.start_with? "6"
|
101
|
+
tracker.options[:rails3] = true
|
102
|
+
tracker.options[:rails4] = true
|
103
|
+
tracker.options[:rails5] = true
|
104
|
+
tracker.options[:rails6] = true
|
105
|
+
Brakeman.notify "[Notice] Detected Rails 6 application"
|
100
106
|
end
|
101
107
|
end
|
102
108
|
end
|
@@ -107,12 +113,20 @@ module Brakeman
|
|
107
113
|
end
|
108
114
|
end
|
109
115
|
|
116
|
+
def rails_version
|
117
|
+
# This needs to be here because Util#rails_version calls Tracker::Config#rails_version
|
118
|
+
# but Tracker::Config includes Util...
|
119
|
+
@rails_version
|
120
|
+
end
|
121
|
+
|
110
122
|
def set_ruby_version version
|
123
|
+
@ruby_version = extract_version(version)
|
124
|
+
end
|
125
|
+
|
126
|
+
def extract_version version
|
111
127
|
return unless version.is_a? String
|
112
128
|
|
113
|
-
|
114
|
-
self.ruby_version = $1
|
115
|
-
end
|
129
|
+
version[/\d+\.\d+(\.\d+.*)?/]
|
116
130
|
end
|
117
131
|
|
118
132
|
#Returns true if low_version <= RAILS_VERSION <= high_version
|
@@ -122,33 +136,15 @@ module Brakeman
|
|
122
136
|
current_version ||= rails_version
|
123
137
|
return false unless current_version
|
124
138
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
version.each_with_index do |v, i|
|
130
|
-
if v < low_version.fetch(i, 0)
|
131
|
-
return false
|
132
|
-
elsif v > low_version.fetch(i, 0)
|
133
|
-
break
|
134
|
-
end
|
135
|
-
end
|
139
|
+
low = Gem::Version.new(low_version)
|
140
|
+
high = Gem::Version.new(high_version)
|
141
|
+
current = Gem::Version.new(current_version)
|
136
142
|
|
137
|
-
|
138
|
-
if v > high_version.fetch(i, 0)
|
139
|
-
return false
|
140
|
-
elsif v < high_version.fetch(i, 0)
|
141
|
-
break
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
true
|
143
|
+
current.between?(low, high)
|
146
144
|
end
|
147
145
|
|
148
146
|
def session_settings
|
149
|
-
@rails
|
150
|
-
@rails[:action_controller][:session]
|
147
|
+
@rails.dig(:action_controller, :session)
|
151
148
|
end
|
152
|
-
|
153
149
|
end
|
154
150
|
end
|
@@ -49,7 +49,7 @@ module Brakeman
|
|
49
49
|
include Brakeman::Util
|
50
50
|
|
51
51
|
def initialize
|
52
|
-
@constants =
|
52
|
+
@constants = {}
|
53
53
|
end
|
54
54
|
|
55
55
|
def size
|
@@ -103,6 +103,7 @@ module Brakeman
|
|
103
103
|
end
|
104
104
|
|
105
105
|
base_name = Constants.get_constant_base_name(name)
|
106
|
+
@constants[base_name] ||= []
|
106
107
|
@constants[base_name] << Constant.new(name, value, context)
|
107
108
|
end
|
108
109
|
|
data/lib/brakeman/util.rb
CHANGED
@@ -94,11 +94,21 @@ module Brakeman::Util
|
|
94
94
|
# end
|
95
95
|
# names #["bob"]
|
96
96
|
def hash_iterate hash
|
97
|
+
hash = remove_kwsplat(hash)
|
98
|
+
|
97
99
|
1.step(hash.length - 1, 2) do |i|
|
98
100
|
yield hash[i], hash[i + 1]
|
99
101
|
end
|
100
102
|
end
|
101
103
|
|
104
|
+
def remove_kwsplat exp
|
105
|
+
if exp.any? { |e| node_type? e, :kwsplat }
|
106
|
+
exp.reject { |e| node_type? e, :kwsplat }
|
107
|
+
else
|
108
|
+
exp
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
102
112
|
#Insert value into Hash Sexp
|
103
113
|
def hash_insert hash, key, value
|
104
114
|
index = 1
|
@@ -264,6 +274,13 @@ module Brakeman::Util
|
|
264
274
|
node_type? exp, :const, :colon2, :colon3
|
265
275
|
end
|
266
276
|
|
277
|
+
def kwsplat? exp
|
278
|
+
exp.is_a? Sexp and
|
279
|
+
exp.node_type == :hash and
|
280
|
+
exp[1].is_a? Sexp and
|
281
|
+
exp[1].node_type == :kwsplat
|
282
|
+
end
|
283
|
+
|
267
284
|
#Check if _exp_ is a Sexp.
|
268
285
|
def sexp? exp
|
269
286
|
exp.is_a? Sexp
|
@@ -329,158 +346,12 @@ module Brakeman::Util
|
|
329
346
|
@tracker.config.rails_version
|
330
347
|
end
|
331
348
|
|
332
|
-
#Return file name related to given warning. Uses +warning.file+ if it exists
|
333
|
-
def file_for warning, tracker = nil
|
334
|
-
if tracker.nil?
|
335
|
-
tracker = @tracker || self.tracker
|
336
|
-
end
|
337
|
-
|
338
|
-
if warning.file
|
339
|
-
File.expand_path warning.file, tracker.app_path
|
340
|
-
elsif warning.template and warning.template.file
|
341
|
-
warning.template.file
|
342
|
-
else
|
343
|
-
case warning.warning_set
|
344
|
-
when :controller
|
345
|
-
file_by_name warning.controller, :controller, tracker
|
346
|
-
when :template
|
347
|
-
file_by_name warning.template.name, :template, tracker
|
348
|
-
when :model
|
349
|
-
file_by_name warning.model, :model, tracker
|
350
|
-
when :warning
|
351
|
-
file_by_name warning.class, nil, tracker
|
352
|
-
else
|
353
|
-
nil
|
354
|
-
end
|
355
|
-
end
|
356
|
-
end
|
357
|
-
|
358
|
-
#Attempt to determine path to context file based on the reported name
|
359
|
-
#in the warning.
|
360
|
-
#
|
361
|
-
#For example,
|
362
|
-
#
|
363
|
-
# file_by_name FileController #=> "/rails/root/app/controllers/file_controller.rb
|
364
|
-
def file_by_name name, type, tracker = nil
|
365
|
-
return nil unless name
|
366
|
-
string_name = name.to_s
|
367
|
-
name = name.to_sym
|
368
|
-
|
369
|
-
unless type
|
370
|
-
if string_name =~ /Controller$/
|
371
|
-
type = :controller
|
372
|
-
elsif camelize(string_name) == string_name # This is not always true
|
373
|
-
type = :model
|
374
|
-
else
|
375
|
-
type = :template
|
376
|
-
end
|
377
|
-
end
|
378
|
-
|
379
|
-
path = tracker.app_path
|
380
|
-
|
381
|
-
case type
|
382
|
-
when :controller
|
383
|
-
if tracker.controllers[name]
|
384
|
-
path = tracker.controllers[name].file
|
385
|
-
else
|
386
|
-
path += "/app/controllers/#{underscore(string_name)}.rb"
|
387
|
-
end
|
388
|
-
when :model
|
389
|
-
if tracker.models[name]
|
390
|
-
path = tracker.models[name].file
|
391
|
-
else
|
392
|
-
path += "/app/models/#{underscore(string_name)}.rb"
|
393
|
-
end
|
394
|
-
when :template
|
395
|
-
if tracker.templates[name] and tracker.templates[name].file
|
396
|
-
path = tracker.templates[name].file
|
397
|
-
elsif string_name.include? " "
|
398
|
-
name = string_name.split[0].to_sym
|
399
|
-
path = file_for tracker, name, :template
|
400
|
-
else
|
401
|
-
path = nil
|
402
|
-
end
|
403
|
-
end
|
404
|
-
|
405
|
-
path
|
406
|
-
end
|
407
|
-
|
408
|
-
#Return array of lines surrounding the warning location from the original
|
409
|
-
#file.
|
410
|
-
def context_for app_tree, warning, tracker = nil
|
411
|
-
file = file_for warning, tracker
|
412
|
-
context = []
|
413
|
-
return context unless warning.line and file and @app_tree.path_exists? file
|
414
|
-
|
415
|
-
current_line = 0
|
416
|
-
start_line = warning.line - 5
|
417
|
-
end_line = warning.line + 5
|
418
|
-
|
419
|
-
start_line = 1 if start_line < 0
|
420
|
-
|
421
|
-
File.open file do |f|
|
422
|
-
f.each_line do |line|
|
423
|
-
current_line += 1
|
424
|
-
|
425
|
-
next if line.strip == ""
|
426
|
-
|
427
|
-
if current_line > end_line
|
428
|
-
break
|
429
|
-
end
|
430
|
-
|
431
|
-
if current_line >= start_line
|
432
|
-
context << [current_line, line]
|
433
|
-
end
|
434
|
-
end
|
435
|
-
end
|
436
|
-
|
437
|
-
context
|
438
|
-
end
|
439
|
-
|
440
|
-
def relative_path file
|
441
|
-
pname = Pathname.new file
|
442
|
-
if file and not file.empty? and pname.absolute?
|
443
|
-
pname.relative_path_from(Pathname.new(@tracker.app_path)).to_s
|
444
|
-
else
|
445
|
-
file
|
446
|
-
end
|
447
|
-
end
|
448
|
-
|
449
349
|
#Convert path/filename to view name
|
450
350
|
#
|
451
351
|
# views/test/something.html.erb -> test/something
|
452
352
|
def template_path_to_name path
|
453
|
-
names = path.split("/")
|
353
|
+
names = path.relative.split("/")
|
454
354
|
names.last.gsub!(/(\.(html|js)\..*|\.(rhtml|haml|erb|slim))$/, '')
|
455
355
|
names[(names.index("views") + 1)..-1].join("/").to_sym
|
456
356
|
end
|
457
|
-
|
458
|
-
def github_url file, line=nil
|
459
|
-
if repo_url = @tracker.options[:github_url] and file and not file.empty? and file.start_with? '/'
|
460
|
-
url = "#{repo_url}/#{relative_path(file)}"
|
461
|
-
url << "#L#{line}" if line
|
462
|
-
else
|
463
|
-
nil
|
464
|
-
end
|
465
|
-
end
|
466
|
-
|
467
|
-
def truncate_table str
|
468
|
-
@terminal_width ||= if @tracker.options[:table_width]
|
469
|
-
@tracker.options[:table_width]
|
470
|
-
elsif $stdin && $stdin.tty?
|
471
|
-
Brakeman.load_brakeman_dependency 'highline'
|
472
|
-
::HighLine.new.terminal_size[0]
|
473
|
-
else
|
474
|
-
80
|
475
|
-
end
|
476
|
-
lines = str.lines
|
477
|
-
|
478
|
-
lines.map do |line|
|
479
|
-
if line.chomp.length > @terminal_width
|
480
|
-
line[0..(@terminal_width - 3)] + ">>\n"
|
481
|
-
else
|
482
|
-
line
|
483
|
-
end
|
484
|
-
end.join
|
485
|
-
end
|
486
357
|
end
|