brakeman-lib 4.9.0 → 5.0.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 +44 -0
- data/README.md +1 -1
- data/lib/brakeman.rb +10 -0
- data/lib/brakeman/app_tree.rb +36 -3
- data/lib/brakeman/checks/base_check.rb +7 -1
- data/lib/brakeman/checks/check_execute.rb +2 -1
- data/lib/brakeman/checks/check_model_attributes.rb +1 -1
- data/lib/brakeman/checks/check_regex_dos.rb +1 -1
- data/lib/brakeman/checks/check_sql.rb +2 -2
- data/lib/brakeman/checks/check_unsafe_reflection_methods.rb +68 -0
- data/lib/brakeman/checks/check_verb_confusion.rb +75 -0
- data/lib/brakeman/file_parser.rb +24 -18
- data/lib/brakeman/options.rb +5 -1
- data/lib/brakeman/parsers/template_parser.rb +2 -3
- data/lib/brakeman/processors/alias_processor.rb +20 -4
- data/lib/brakeman/processors/controller_processor.rb +1 -1
- data/lib/brakeman/processors/haml_template_processor.rb +8 -1
- data/lib/brakeman/processors/lib/call_conversion_helper.rb +1 -1
- data/lib/brakeman/processors/lib/file_type_detector.rb +64 -0
- data/lib/brakeman/processors/lib/rails3_config_processor.rb +16 -16
- data/lib/brakeman/processors/output_processor.rb +1 -1
- data/lib/brakeman/processors/template_alias_processor.rb +5 -0
- data/lib/brakeman/report.rb +15 -0
- data/lib/brakeman/report/report_base.rb +0 -2
- data/lib/brakeman/report/report_csv.rb +37 -60
- data/lib/brakeman/report/report_junit.rb +2 -2
- data/lib/brakeman/report/report_sarif.rb +114 -0
- data/lib/brakeman/report/report_sonar.rb +38 -0
- data/lib/brakeman/report/report_tabs.rb +1 -1
- data/lib/brakeman/report/report_text.rb +1 -1
- data/lib/brakeman/rescanner.rb +7 -5
- data/lib/brakeman/scanner.rb +44 -18
- data/lib/brakeman/tracker.rb +6 -0
- data/lib/brakeman/tracker/config.rb +76 -1
- data/lib/brakeman/tracker/controller.rb +1 -1
- data/lib/brakeman/util.rb +9 -4
- data/lib/brakeman/version.rb +1 -1
- data/lib/brakeman/warning.rb +10 -2
- data/lib/brakeman/warning_codes.rb +2 -0
- data/lib/ruby_parser/bm_sexp.rb +9 -9
- metadata +22 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 59808cb56d2701ba4806eaf3e8fdaa70e3b15d3578badb1a93177ae60a03fe16
|
|
4
|
+
data.tar.gz: d74f4ffa7620d6ae48cddc85ad661548c6c21fa807306a987e31343990e33a09
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1319c8e5a981305d8ab91885a9edfe475240014e7f3e19d2f4e24da8eabc0c0cf355cd8ef387091291dd4a7d3a29fc35309531e6edce6606100b5a7c48f24b64
|
|
7
|
+
data.tar.gz: 02356cced5a4aaae709a3f237319af4bf4f511224762c41bb61d1130813385d27e922722771d037ef1773271db642431be689f249b72396f7800730606ad3ba3
|
data/CHANGES.md
CHANGED
|
@@ -1,3 +1,47 @@
|
|
|
1
|
+
# 5.0.0 - 2021-01-26
|
|
2
|
+
|
|
3
|
+
* Ignore `uuid` as a safe attribute
|
|
4
|
+
* Collapse `__send__` calls
|
|
5
|
+
* Ignore `Tempfile#path` in shell commands
|
|
6
|
+
* Ignore development environment
|
|
7
|
+
* Revamp CSV report to a CSV list of warnings
|
|
8
|
+
* Set Rails configuration defaults based on `load_defaults` version
|
|
9
|
+
* Add check for (more) unsafe method reflection
|
|
10
|
+
* Suggest using `--force` if no Rails application is detected
|
|
11
|
+
* Add Sonarqube report format (Adam England)
|
|
12
|
+
* Add check for potential HTTP verb confusion
|
|
13
|
+
* Add `--[no-]skip-vendor` option
|
|
14
|
+
* Scan (almost) all Ruby files in project
|
|
15
|
+
|
|
16
|
+
# 4.10.1 - 2020-12-24
|
|
17
|
+
|
|
18
|
+
* Declare REXML as a dependency (Ruby 3.0 compatibility)
|
|
19
|
+
* Use `Sexp#sexp_body` instead of `Sexp#[..]` (Ruby 3.0 compatibility)
|
|
20
|
+
* Prevent render loops when template names are absolute paths
|
|
21
|
+
* Ensure RubyParser is passed file path as a String
|
|
22
|
+
* Support new Haml 5.2.0 escaping method
|
|
23
|
+
|
|
24
|
+
# 5.0.0.pre1 - 2020-11-17
|
|
25
|
+
|
|
26
|
+
* Add check for (more) unsafe method reflection
|
|
27
|
+
* Suggest using `--force` if no Rails application is detected
|
|
28
|
+
* Add Sonarqube report format (Adam England)
|
|
29
|
+
* Add check for potential HTTP verb confusion
|
|
30
|
+
* Add `--[no-]skip-vendor` option
|
|
31
|
+
* Scan (almost) all Ruby files in project
|
|
32
|
+
* Add support for Haml 5.2.0
|
|
33
|
+
|
|
34
|
+
# 4.10.0 - 2020-09-28
|
|
35
|
+
|
|
36
|
+
* Add SARIF report format (Steve Winton)
|
|
37
|
+
|
|
38
|
+
# 4.9.1 - 2020-09-04
|
|
39
|
+
|
|
40
|
+
* Check `chomp`ed strings for SQL injection
|
|
41
|
+
* Use version from `active_record` for non-Rails apps (Ulysse Buonomo)
|
|
42
|
+
* Always set line number for joined arrays
|
|
43
|
+
* Avoid warning about missing `attr_accessible` if `protected_attributes` gem is used
|
|
44
|
+
|
|
1
45
|
# 4.9.0 - 2020-08-04
|
|
2
46
|
|
|
3
47
|
* Add check for CVE-2020-8166 (Jamie Finnigan)
|
data/README.md
CHANGED
|
@@ -76,7 +76,7 @@ To specify an output file for the results:
|
|
|
76
76
|
|
|
77
77
|
brakeman -o output_file
|
|
78
78
|
|
|
79
|
-
The output format is determined by the file extension or by using the `-f` option. Current options are: `text`, `html`, `tabs`, `json`, `junit`, `markdown`, `csv`, and `
|
|
79
|
+
The output format is determined by the file extension or by using the `-f` option. Current options are: `text`, `html`, `tabs`, `json`, `junit`, `markdown`, `csv`, `codeclimate`, and `sonar`.
|
|
80
80
|
|
|
81
81
|
Multiple output files can be specified:
|
|
82
82
|
|
data/lib/brakeman.rb
CHANGED
|
@@ -66,6 +66,7 @@ module Brakeman
|
|
|
66
66
|
# * :run_checks - array of checks to run (run all if not specified)
|
|
67
67
|
# * :safe_methods - array of methods to consider safe
|
|
68
68
|
# * :skip_libs - do not process lib/ directory (default: false)
|
|
69
|
+
# * :skip_vendor - do not process vendor/ directory (default: true)
|
|
69
70
|
# * :skip_checks - checks not to run (run all if not specified)
|
|
70
71
|
# * :absolute_paths - show absolute path of each file (default: false)
|
|
71
72
|
# * :summary_only - only output summary section of report for plain/table (:summary_only, :no_summary, true)
|
|
@@ -191,6 +192,7 @@ module Brakeman
|
|
|
191
192
|
:report_progress => true,
|
|
192
193
|
:safe_methods => Set.new,
|
|
193
194
|
:skip_checks => Set.new,
|
|
195
|
+
:skip_vendor => true,
|
|
194
196
|
}
|
|
195
197
|
end
|
|
196
198
|
|
|
@@ -237,6 +239,10 @@ module Brakeman
|
|
|
237
239
|
[:to_table]
|
|
238
240
|
when :junit, :to_junit
|
|
239
241
|
[:to_junit]
|
|
242
|
+
when :sarif, :to_sarif
|
|
243
|
+
[:to_sarif]
|
|
244
|
+
when :sonar, :to_sonar
|
|
245
|
+
[:to_sonar]
|
|
240
246
|
else
|
|
241
247
|
[:to_text]
|
|
242
248
|
end
|
|
@@ -266,6 +272,10 @@ module Brakeman
|
|
|
266
272
|
:to_table
|
|
267
273
|
when /\.junit$/i
|
|
268
274
|
:to_junit
|
|
275
|
+
when /\.sarif$/i
|
|
276
|
+
:to_sarif
|
|
277
|
+
when /\.sonar$/i
|
|
278
|
+
:to_sonar
|
|
269
279
|
else
|
|
270
280
|
:to_text
|
|
271
281
|
end
|
data/lib/brakeman/app_tree.rb
CHANGED
|
@@ -21,6 +21,7 @@ module Brakeman
|
|
|
21
21
|
end
|
|
22
22
|
init_options[:additional_libs_path] = options[:additional_libs_path]
|
|
23
23
|
init_options[:engine_paths] = options[:engine_paths]
|
|
24
|
+
init_options[:skip_vendor] = options[:skip_vendor]
|
|
24
25
|
new(root, init_options)
|
|
25
26
|
end
|
|
26
27
|
|
|
@@ -62,6 +63,7 @@ module Brakeman
|
|
|
62
63
|
@engine_paths = init_options[:engine_paths] || []
|
|
63
64
|
@absolute_engine_paths = @engine_paths.select { |path| path.start_with?(File::SEPARATOR) }
|
|
64
65
|
@relative_engine_paths = @engine_paths - @absolute_engine_paths
|
|
66
|
+
@skip_vendor = init_options[:skip_vendor]
|
|
65
67
|
@gemspec = nil
|
|
66
68
|
@root_search_pattern = nil
|
|
67
69
|
end
|
|
@@ -96,6 +98,10 @@ module Brakeman
|
|
|
96
98
|
end
|
|
97
99
|
end
|
|
98
100
|
|
|
101
|
+
def ruby_file_paths
|
|
102
|
+
find_paths(".").uniq
|
|
103
|
+
end
|
|
104
|
+
|
|
99
105
|
def initializer_paths
|
|
100
106
|
@initializer_paths ||= prioritize_concerns(find_paths("config/initializers"))
|
|
101
107
|
end
|
|
@@ -109,8 +115,8 @@ module Brakeman
|
|
|
109
115
|
end
|
|
110
116
|
|
|
111
117
|
def template_paths
|
|
112
|
-
@template_paths ||= find_paths("
|
|
113
|
-
|
|
118
|
+
@template_paths ||= find_paths(".", "*.{#{VIEW_EXTENSIONS}}") +
|
|
119
|
+
find_paths("**", "*.{erb,haml,slim}").reject { |path| File.basename(path).count(".") > 1 }
|
|
114
120
|
end
|
|
115
121
|
|
|
116
122
|
def layout_exists?(name)
|
|
@@ -163,7 +169,8 @@ module Brakeman
|
|
|
163
169
|
def select_files(paths)
|
|
164
170
|
paths = select_only_files(paths)
|
|
165
171
|
paths = reject_skipped_files(paths)
|
|
166
|
-
convert_to_file_paths(paths)
|
|
172
|
+
paths = convert_to_file_paths(paths)
|
|
173
|
+
reject_global_excludes(paths)
|
|
167
174
|
end
|
|
168
175
|
|
|
169
176
|
def select_only_files(paths)
|
|
@@ -182,6 +189,32 @@ module Brakeman
|
|
|
182
189
|
end
|
|
183
190
|
end
|
|
184
191
|
|
|
192
|
+
EXCLUDED_PATHS = %w[
|
|
193
|
+
/generators/
|
|
194
|
+
lib/tasks/
|
|
195
|
+
lib/templates/
|
|
196
|
+
db/
|
|
197
|
+
spec/
|
|
198
|
+
test/
|
|
199
|
+
tmp/
|
|
200
|
+
public/
|
|
201
|
+
log/
|
|
202
|
+
]
|
|
203
|
+
|
|
204
|
+
def reject_global_excludes(paths)
|
|
205
|
+
paths.reject do |path|
|
|
206
|
+
relative_path = path.relative
|
|
207
|
+
|
|
208
|
+
if @skip_vendor and relative_path.include? 'vendor/'
|
|
209
|
+
true
|
|
210
|
+
else
|
|
211
|
+
EXCLUDED_PATHS.any? do |excluded|
|
|
212
|
+
relative_path.include? excluded
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
|
|
185
218
|
def match_path files, path
|
|
186
219
|
absolute_path = Pathname.new(path)
|
|
187
220
|
# relative root never has a leading separator. But, we use a leading
|
|
@@ -40,7 +40,7 @@ class Brakeman::BaseCheck < Brakeman::SexpProcessor
|
|
|
40
40
|
@mass_assign_disabled = nil
|
|
41
41
|
@has_user_input = nil
|
|
42
42
|
@in_array = false
|
|
43
|
-
@safe_input_attributes = Set[:to_i, :to_f, :arel_table, :id]
|
|
43
|
+
@safe_input_attributes = Set[:to_i, :to_f, :arel_table, :id, :uuid]
|
|
44
44
|
@comparison_ops = Set[:==, :!=, :>, :<, :>=, :<=]
|
|
45
45
|
end
|
|
46
46
|
|
|
@@ -151,6 +151,12 @@ class Brakeman::BaseCheck < Brakeman::SexpProcessor
|
|
|
151
151
|
method[-1] == "?"
|
|
152
152
|
end
|
|
153
153
|
|
|
154
|
+
TEMP_FILE_PATH = s(:call, s(:call, s(:const, :Tempfile), :new), :path).freeze
|
|
155
|
+
|
|
156
|
+
def temp_file_path? exp
|
|
157
|
+
exp == TEMP_FILE_PATH
|
|
158
|
+
end
|
|
159
|
+
|
|
154
160
|
#Report a warning
|
|
155
161
|
def warn options
|
|
156
162
|
extra_opts = { :check => self.class.to_s }
|
|
@@ -204,11 +204,12 @@ class Brakeman::CheckExecute < Brakeman::BaseCheck
|
|
|
204
204
|
next if node_type? e, :lit, :str
|
|
205
205
|
next if SAFE_VALUES.include? e
|
|
206
206
|
next if shell_escape? e
|
|
207
|
+
next if temp_file_path? e
|
|
207
208
|
|
|
208
209
|
if node_type? e, :if
|
|
209
210
|
# If we're in a conditional, evaluate the `then` and `else` clauses to
|
|
210
211
|
# see if they're dangerous.
|
|
211
|
-
if res = dangerous?(e.
|
|
212
|
+
if res = dangerous?(e.sexp_body.sexp_body)
|
|
212
213
|
return res
|
|
213
214
|
end
|
|
214
215
|
elsif node_type? e, :or, :evstr, :dstr
|
|
@@ -8,7 +8,7 @@ class Brakeman::CheckModelAttributes < Brakeman::BaseCheck
|
|
|
8
8
|
@description = "Reports models which do not use attr_restricted and warns on models that use attr_protected"
|
|
9
9
|
|
|
10
10
|
def run_check
|
|
11
|
-
return if mass_assign_disabled?
|
|
11
|
+
return if mass_assign_disabled? or tracker.config.has_gem?(:protected_attributes)
|
|
12
12
|
|
|
13
13
|
#Roll warnings into one warning for all models
|
|
14
14
|
if tracker.options[:collapse_mass_assignment]
|
|
@@ -393,7 +393,7 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
|
|
|
393
393
|
nil
|
|
394
394
|
end
|
|
395
395
|
|
|
396
|
-
TO_STRING_METHODS = [:to_s, :squish, :strip, :strip_heredoc]
|
|
396
|
+
TO_STRING_METHODS = [:chomp, :to_s, :squish, :strip, :strip_heredoc]
|
|
397
397
|
|
|
398
398
|
#Returns value if interpolated value is not something safe
|
|
399
399
|
def unsafe_string_interp? exp
|
|
@@ -576,7 +576,7 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
|
|
|
576
576
|
:sanitize_sql_for_assignment, :sanitize_sql_for_conditions, :sanitize_sql_hash,
|
|
577
577
|
:sanitize_sql_hash_for_assignment, :sanitize_sql_hash_for_conditions,
|
|
578
578
|
:to_sql, :sanitize, :primary_key, :table_name_prefix, :table_name_suffix,
|
|
579
|
-
:where_values_hash, :foreign_key
|
|
579
|
+
:where_values_hash, :foreign_key, :uuid
|
|
580
580
|
]
|
|
581
581
|
|
|
582
582
|
def safe_value? exp
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
require 'brakeman/checks/base_check'
|
|
2
|
+
|
|
3
|
+
class Brakeman::CheckUnsafeReflectionMethods < Brakeman::BaseCheck
|
|
4
|
+
Brakeman::Checks.add self
|
|
5
|
+
|
|
6
|
+
@description = "Checks for unsafe reflection to access methods"
|
|
7
|
+
|
|
8
|
+
def run_check
|
|
9
|
+
check_method
|
|
10
|
+
check_tap
|
|
11
|
+
check_to_proc
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def check_method
|
|
15
|
+
tracker.find_call(method: :method, nested: true).each do |result|
|
|
16
|
+
argument = result[:call].first_arg
|
|
17
|
+
|
|
18
|
+
if user_input = include_user_input?(argument)
|
|
19
|
+
warn_unsafe_reflection(result, user_input)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def check_tap
|
|
25
|
+
tracker.find_call(method: :tap, nested: true).each do |result|
|
|
26
|
+
argument = result[:call].first_arg
|
|
27
|
+
|
|
28
|
+
# Argument is passed like a.tap(&argument)
|
|
29
|
+
if node_type? argument, :block_pass
|
|
30
|
+
argument = argument.value
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
if user_input = include_user_input?(argument)
|
|
34
|
+
warn_unsafe_reflection(result, user_input)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def check_to_proc
|
|
40
|
+
tracker.find_call(method: :to_proc, nested: true).each do |result|
|
|
41
|
+
target = result[:call].target
|
|
42
|
+
|
|
43
|
+
if user_input = include_user_input?(target)
|
|
44
|
+
warn_unsafe_reflection(result, user_input)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def warn_unsafe_reflection result, input
|
|
50
|
+
return unless original? result
|
|
51
|
+
method = result[:call].method
|
|
52
|
+
|
|
53
|
+
confidence = if input.type == :params
|
|
54
|
+
:high
|
|
55
|
+
else
|
|
56
|
+
:medium
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
message = msg("Unsafe reflection method ", msg_code(method), " called with ", msg_input(input))
|
|
60
|
+
|
|
61
|
+
warn :result => result,
|
|
62
|
+
:warning_type => "Remote Code Execution",
|
|
63
|
+
:warning_code => :unsafe_method_reflection,
|
|
64
|
+
:message => message,
|
|
65
|
+
:user_input => input,
|
|
66
|
+
:confidence => confidence
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
require 'brakeman/checks/base_check'
|
|
2
|
+
|
|
3
|
+
class Brakeman::CheckVerbConfusion < Brakeman::BaseCheck
|
|
4
|
+
Brakeman::Checks.add self
|
|
5
|
+
|
|
6
|
+
@description = "Check for uses of `request.get?` that might have unintentional behavior"
|
|
7
|
+
|
|
8
|
+
#Process calls
|
|
9
|
+
def run_check
|
|
10
|
+
calls = tracker.find_call(target: :request, methods: [:get?])
|
|
11
|
+
|
|
12
|
+
calls.each do |call|
|
|
13
|
+
process_result call
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def process_result result
|
|
18
|
+
@current_result = result
|
|
19
|
+
@matched_call = result[:call]
|
|
20
|
+
klass = tracker.find_class(result[:location][:class])
|
|
21
|
+
|
|
22
|
+
# TODO: abstract into tracker.find_location ?
|
|
23
|
+
if klass.nil?
|
|
24
|
+
Brakeman.debug "No class found: #{result[:location][:class]}"
|
|
25
|
+
return
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
method = klass.get_method(result[:location][:method])
|
|
29
|
+
|
|
30
|
+
if method.nil?
|
|
31
|
+
Brakeman.debug "No method found: #{result[:location][:method]}"
|
|
32
|
+
return
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
process method[:src]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def process_if exp
|
|
39
|
+
if exp.condition == @matched_call
|
|
40
|
+
# Found `if request.get?`
|
|
41
|
+
|
|
42
|
+
# Do not warn if there is an `elsif` clause
|
|
43
|
+
if node_type? exp.else_clause, :if
|
|
44
|
+
return exp
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
warn_about_result @current_result, exp
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
exp
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def warn_about_result result, code
|
|
54
|
+
return unless original? result
|
|
55
|
+
|
|
56
|
+
confidence = :weak
|
|
57
|
+
message = msg('Potential HTTP verb confusion. ',
|
|
58
|
+
msg_code('HEAD'),
|
|
59
|
+
' is routed like ',
|
|
60
|
+
msg_code('GET'),
|
|
61
|
+
' but ',
|
|
62
|
+
msg_code('request.get?'),
|
|
63
|
+
' will return ',
|
|
64
|
+
msg_code('false')
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
warn :result => result,
|
|
68
|
+
:warning_type => "HTTP Verb Confusion",
|
|
69
|
+
:warning_code => :http_verb_confusion,
|
|
70
|
+
:message => message,
|
|
71
|
+
:code => code,
|
|
72
|
+
:user_input => result[:call],
|
|
73
|
+
:confidence => confidence
|
|
74
|
+
end
|
|
75
|
+
end
|
data/lib/brakeman/file_parser.rb
CHANGED
|
@@ -3,50 +3,56 @@ module Brakeman
|
|
|
3
3
|
|
|
4
4
|
# This class handles reading and parsing files.
|
|
5
5
|
class FileParser
|
|
6
|
-
attr_reader :file_list
|
|
6
|
+
attr_reader :file_list, :errors
|
|
7
7
|
|
|
8
|
-
def initialize
|
|
9
|
-
@
|
|
10
|
-
@timeout =
|
|
11
|
-
@
|
|
12
|
-
@
|
|
8
|
+
def initialize app_tree, timeout
|
|
9
|
+
@app_tree = app_tree
|
|
10
|
+
@timeout = timeout
|
|
11
|
+
@file_list = []
|
|
12
|
+
@errors = []
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
def parse_files list
|
|
16
|
-
read_files list
|
|
15
|
+
def parse_files list
|
|
16
|
+
read_files list do |path, contents|
|
|
17
17
|
if ast = parse_ruby(contents, path.relative)
|
|
18
18
|
ASTFile.new(path, ast)
|
|
19
19
|
end
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
def read_files list
|
|
24
|
-
@file_list[type] ||= []
|
|
25
|
-
|
|
23
|
+
def read_files list
|
|
26
24
|
list.each do |path|
|
|
27
25
|
file = @app_tree.file_path(path)
|
|
28
26
|
|
|
29
27
|
result = yield file, file.read
|
|
28
|
+
|
|
30
29
|
if result
|
|
31
|
-
@file_list
|
|
30
|
+
@file_list << result
|
|
32
31
|
end
|
|
33
32
|
end
|
|
34
33
|
end
|
|
35
34
|
|
|
35
|
+
# _path_ can be a string or a Brakeman::FilePath
|
|
36
36
|
def parse_ruby input, path
|
|
37
|
+
if path.is_a? Brakeman::FilePath
|
|
38
|
+
path = path.relative
|
|
39
|
+
end
|
|
40
|
+
|
|
37
41
|
begin
|
|
38
42
|
Brakeman.debug "Parsing #{path}"
|
|
39
43
|
RubyParser.new.parse input, path, @timeout
|
|
40
44
|
rescue Racc::ParseError => e
|
|
41
|
-
|
|
42
|
-
nil
|
|
45
|
+
error e.exception(e.message + "\nCould not parse #{path}")
|
|
43
46
|
rescue Timeout::Error => e
|
|
44
|
-
|
|
45
|
-
nil
|
|
47
|
+
error Exception.new("Parsing #{path} took too long (> #{@timeout} seconds). Try increasing the limit with --parser-timeout")
|
|
46
48
|
rescue => e
|
|
47
|
-
|
|
48
|
-
nil
|
|
49
|
+
error e.exception(e.message + "\nWhile processing #{path}")
|
|
49
50
|
end
|
|
50
51
|
end
|
|
52
|
+
|
|
53
|
+
def error exception
|
|
54
|
+
@errors << exception
|
|
55
|
+
nil
|
|
56
|
+
end
|
|
51
57
|
end
|
|
52
58
|
end
|