brakeman-min 6.1.1 → 6.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.md +24 -0
- data/README.md +5 -1
- data/lib/brakeman/app_tree.rb +20 -5
- data/lib/brakeman/checks/check_eol_ruby.rb +1 -0
- data/lib/brakeman/checks/check_render.rb +6 -1
- data/lib/brakeman/checks/check_session_settings.rb +2 -3
- data/lib/brakeman/checks/check_unscoped_find.rb +1 -1
- data/lib/brakeman/file_parser.rb +34 -2
- data/lib/brakeman/options.rb +34 -4
- data/lib/brakeman/parsers/erubis_patch.rb +11 -0
- data/lib/brakeman/parsers/rails2_erubis.rb +3 -0
- data/lib/brakeman/parsers/rails2_xss_plugin_erubis.rb +4 -0
- data/lib/brakeman/parsers/rails3_erubis.rb +5 -1
- data/lib/brakeman/parsers/slim_embedded.rb +2 -0
- data/lib/brakeman/processors/alias_processor.rb +41 -15
- data/lib/brakeman/report/pager.rb +1 -1
- data/lib/brakeman/report/report_markdown.rb +1 -1
- data/lib/brakeman/report/report_table.rb +2 -2
- data/lib/brakeman/report/report_tabs.rb +0 -1
- data/lib/brakeman/report/report_text.rb +8 -1
- data/lib/brakeman/scanner.rb +2 -2
- data/lib/brakeman/tracker/config.rb +9 -1
- data/lib/brakeman/util.rb +1 -3
- data/lib/brakeman/version.rb +1 -1
- data/lib/brakeman/warning.rb +1 -1
- data/lib/brakeman.rb +4 -3
- data/lib/ruby_parser/bm_sexp.rb +5 -1
- metadata +20 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9a6b0a21e0bcd1760b239f11c2350abd2b3aeef743925e568313f73fe7d04723
|
4
|
+
data.tar.gz: 054611dc13f667e53b68ec0491973a85d29ed2d47015e0ea7fa623f47b28672f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 821a08146a597fbb48cd08312d3310e2d20401bd4d53403beb74615ec2c3cce261ea9f672a42243ffdd5c748a3abec65acf14930fb3f8f59014aabfae6ea65ee
|
7
|
+
data.tar.gz: a4c29407ad9ac73dba0c93f7f3d5e08056e00351ffc3406c01390e2f64386982053382f50d65c41b94613eaecae28180cb1001c9afce554d265fb7c1fb25b5ce
|
data/CHANGES.md
CHANGED
@@ -1,3 +1,27 @@
|
|
1
|
+
# 6.2.0 - 2024-08-22
|
2
|
+
|
3
|
+
* Add `--show-ignored` option (Gabriel Zayas)
|
4
|
+
* Add optional support for Prism parser
|
5
|
+
* Warn about unscoped finds with `find_by!`
|
6
|
+
* Treat `::X` and `X` the same, for now (Jill Klang)
|
7
|
+
* Fix compatibility with default frozen string literals (Jean Boussier)
|
8
|
+
* Remediation advice for command injection (Nicholas Barone)
|
9
|
+
* Fix Ruby warnings in test suite (Jean Boussier)
|
10
|
+
* Support YAML aliases in secret configs (Chedli Bourguiba)
|
11
|
+
* Add initial Rails 8 support (Ron Shinall)
|
12
|
+
* Handle mass assignment with splats
|
13
|
+
* Add support for symbolic links (Lu Zhu)
|
14
|
+
|
15
|
+
# 6.1.2 - 2024-02-01
|
16
|
+
|
17
|
+
* Update Highline to 3.0
|
18
|
+
* Add EOL date for Ruby 3.3.0
|
19
|
+
* Avoid copying Sexps that are too large
|
20
|
+
* Avoid detecting `ViewComponentContrib::Base` as dynamic render paths (vividmuimui)
|
21
|
+
* Remove deprecated use of `Kernel#open("|...")`
|
22
|
+
* Remove `safe_yaml` gem dependency
|
23
|
+
* Avoid detecting Phlex components as dynamic render paths (Máximo Mussini)
|
24
|
+
|
1
25
|
# 6.1.1 - 2023-12-24
|
2
26
|
|
3
27
|
* Handle racc as a default gem in Ruby 3.3.0
|
data/README.md
CHANGED
@@ -18,7 +18,7 @@ Using Bundler:
|
|
18
18
|
|
19
19
|
```ruby
|
20
20
|
group :development do
|
21
|
-
gem 'brakeman'
|
21
|
+
gem 'brakeman', require: false
|
22
22
|
end
|
23
23
|
```
|
24
24
|
|
@@ -133,6 +133,10 @@ To create and manage this file, use:
|
|
133
133
|
|
134
134
|
brakeman -I
|
135
135
|
|
136
|
+
If you want to temporarily see the warnings you ignored without affecting the exit code, use:
|
137
|
+
|
138
|
+
brakeman --show-ignored
|
139
|
+
|
136
140
|
# Warning information
|
137
141
|
|
138
142
|
See [warning\_types](docs/warning_types) for more information on the warnings reported by this tool.
|
data/lib/brakeman/app_tree.rb
CHANGED
@@ -50,7 +50,7 @@ module Brakeman
|
|
50
50
|
"#{Regexp.escape f}\\z"
|
51
51
|
end
|
52
52
|
end
|
53
|
-
Regexp.new("(
|
53
|
+
Regexp.new("(?:#{path_regexes.join("|")})")
|
54
54
|
end
|
55
55
|
private_class_method(:regex_for_paths)
|
56
56
|
|
@@ -161,9 +161,21 @@ module Brakeman
|
|
161
161
|
end
|
162
162
|
|
163
163
|
def glob_files(directory, name, extensions = ".rb")
|
164
|
-
|
164
|
+
root_directory = "#{root_search_pattern}#{directory}"
|
165
|
+
patterns = ["#{root_directory}/**/#{name}#{extensions}"]
|
166
|
+
|
167
|
+
Dir.glob("#{root_directory}/**/*", File::FNM_DOTMATCH).each do |path|
|
168
|
+
if File.symlink?(path) && File.directory?(path)
|
169
|
+
symlink_target = File.readlink(path)
|
170
|
+
if Pathname.new(symlink_target).relative?
|
171
|
+
symlink_target = File.join(File.dirname(path), symlink_target)
|
172
|
+
end
|
173
|
+
patterns << "#{search_pattern(symlink_target)}/**/#{name}#{extensions}"
|
174
|
+
end
|
175
|
+
end
|
165
176
|
|
166
|
-
Dir.glob(pattern)
|
177
|
+
files = patterns.flat_map { |pattern| Dir.glob(pattern) }
|
178
|
+
files.uniq
|
167
179
|
end
|
168
180
|
|
169
181
|
def select_files(paths)
|
@@ -237,13 +249,16 @@ module Brakeman
|
|
237
249
|
|
238
250
|
def root_search_pattern
|
239
251
|
return @root_search_pattern if @root_search_pattern
|
252
|
+
@root_search_pattern = search_pattern(@root)
|
253
|
+
end
|
240
254
|
|
255
|
+
def search_pattern(root_dir)
|
241
256
|
abs = @absolute_engine_paths.to_a.map { |path| path.gsub(/#{File::SEPARATOR}+$/, '') }
|
242
257
|
rel = @relative_engine_paths.to_a.map { |path| path.gsub(/#{File::SEPARATOR}+$/, '') }
|
243
258
|
|
244
|
-
roots = ([
|
259
|
+
roots = ([root_dir] + abs).join(",")
|
245
260
|
rel_engines = (rel + [""]).join("/,")
|
246
|
-
|
261
|
+
"{#{roots}}/{#{rel_engines}}"
|
247
262
|
end
|
248
263
|
|
249
264
|
def prioritize_concerns paths
|
@@ -108,6 +108,11 @@ class Brakeman::CheckRender < Brakeman::BaseCheck
|
|
108
108
|
def known_renderable_class? class_name
|
109
109
|
klass = tracker.find_class(class_name)
|
110
110
|
return false if klass.nil?
|
111
|
-
|
111
|
+
knowns = [
|
112
|
+
:"ViewComponent::Base",
|
113
|
+
:"ViewComponentContrib::Base",
|
114
|
+
:"Phlex::HTML"
|
115
|
+
]
|
116
|
+
knowns.any? { |k| klass.ancestor? k }
|
112
117
|
end
|
113
118
|
end
|
@@ -116,10 +116,9 @@ class Brakeman::CheckSessionSettings < Brakeman::BaseCheck
|
|
116
116
|
|
117
117
|
if secrets_file.exists? and not ignored? "secrets.yml" and not ignored? "config/*.yml"
|
118
118
|
yaml = secrets_file.read
|
119
|
-
require '
|
120
|
-
require 'safe_yaml/load'
|
119
|
+
require 'yaml'
|
121
120
|
begin
|
122
|
-
secrets =
|
121
|
+
secrets = YAML.safe_load yaml, aliases: true
|
123
122
|
rescue Psych::SyntaxError, RuntimeError => e
|
124
123
|
Brakeman.notify "[Notice] #{self.class}: Unable to parse `#{secrets_file}`"
|
125
124
|
Brakeman.debug "Failed to parse #{secrets_file}: #{e.inspect}"
|
@@ -24,7 +24,7 @@ class Brakeman::CheckUnscopedFind < Brakeman::BaseCheck
|
|
24
24
|
process_result call
|
25
25
|
end
|
26
26
|
|
27
|
-
tracker.find_call(:
|
27
|
+
tracker.find_call(:methods => [:find_by, :find_by!], :targets => associated_model_names).each do |result|
|
28
28
|
arg = result[:call].first_arg
|
29
29
|
|
30
30
|
if hash? arg and hash_access(arg, :id)
|
data/lib/brakeman/file_parser.rb
CHANGED
@@ -7,7 +7,18 @@ module Brakeman
|
|
7
7
|
class FileParser
|
8
8
|
attr_reader :file_list, :errors
|
9
9
|
|
10
|
-
def initialize app_tree, timeout, parallel = true
|
10
|
+
def initialize app_tree, timeout, parallel = true, use_prism = false
|
11
|
+
@use_prism = use_prism
|
12
|
+
|
13
|
+
if @use_prism
|
14
|
+
begin
|
15
|
+
require 'prism'
|
16
|
+
rescue LoadError => e
|
17
|
+
Brakeman.debug "Asked to use Prism, but failed to load: #{e}"
|
18
|
+
@use_prism = false
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
11
22
|
@app_tree = app_tree
|
12
23
|
@timeout = timeout
|
13
24
|
@file_list = []
|
@@ -73,8 +84,29 @@ module Brakeman
|
|
73
84
|
path = path.relative
|
74
85
|
end
|
75
86
|
|
87
|
+
Brakeman.debug "Parsing #{path}"
|
88
|
+
|
89
|
+
if @use_prism
|
90
|
+
begin
|
91
|
+
parse_with_prism input, path
|
92
|
+
rescue => e
|
93
|
+
Brakeman.debug "Prism failed to parse #{path}: #{e}"
|
94
|
+
|
95
|
+
parse_with_ruby_parser input, path
|
96
|
+
end
|
97
|
+
else
|
98
|
+
parse_with_ruby_parser input, path
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
|
104
|
+
def parse_with_prism input, path
|
105
|
+
Prism::Translation::RubyParser.parse(input, path)
|
106
|
+
end
|
107
|
+
|
108
|
+
def parse_with_ruby_parser input, path
|
76
109
|
begin
|
77
|
-
Brakeman.debug "Parsing #{path}"
|
78
110
|
RubyParser.new.parse input, path, @timeout
|
79
111
|
rescue Racc::ParseError => e
|
80
112
|
raise e.exception(e.message + "\nCould not parse #{path}")
|
data/lib/brakeman/options.rb
CHANGED
@@ -101,6 +101,15 @@ module Brakeman::Options
|
|
101
101
|
options[:rails7] = true
|
102
102
|
end
|
103
103
|
|
104
|
+
opts.on "-8", "--rails8", "Force Rails 8 mode" do
|
105
|
+
options[:rails3] = true
|
106
|
+
options[:rails4] = true
|
107
|
+
options[:rails5] = true
|
108
|
+
options[:rails6] = true
|
109
|
+
options[:rails7] = true
|
110
|
+
options[:rails8] = true
|
111
|
+
end
|
112
|
+
|
104
113
|
opts.separator ""
|
105
114
|
opts.separator "Scanning options:"
|
106
115
|
|
@@ -150,6 +159,23 @@ module Brakeman::Options
|
|
150
159
|
options[:parser_timeout] = timeout
|
151
160
|
end
|
152
161
|
|
162
|
+
opts.on "--[no-]prism", "Use the Prism parser" do |use_prism|
|
163
|
+
if use_prism
|
164
|
+
prism_version = '0.30'
|
165
|
+
|
166
|
+
begin
|
167
|
+
# Specifying minimum version here,
|
168
|
+
# since it can't be in the gem dependency list because it is optional
|
169
|
+
gem 'prism', "~>#{prism_version}"
|
170
|
+
rescue Gem::MissingSpecVersionError, Gem::MissingSpecError, Gem::LoadError => e
|
171
|
+
$stderr.puts "Please install `prism` version #{prism_version} or newer:"
|
172
|
+
raise e
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
options[:use_prism] = use_prism
|
177
|
+
end
|
178
|
+
|
153
179
|
opts.on "-r", "--report-direct", "Only report direct use of untrusted data" do |option|
|
154
180
|
options[:check_arguments] = !option
|
155
181
|
end
|
@@ -202,7 +228,7 @@ module Brakeman::Options
|
|
202
228
|
if check.start_with? "Check"
|
203
229
|
check
|
204
230
|
else
|
205
|
-
"Check"
|
231
|
+
"Check#{check}"
|
206
232
|
end
|
207
233
|
end
|
208
234
|
|
@@ -213,7 +239,7 @@ module Brakeman::Options
|
|
213
239
|
opts.on "-t", "--test Check1,Check2,etc", Array, "Only run the specified checks" do |checks|
|
214
240
|
checks.each_with_index do |s, index|
|
215
241
|
if s[0,5] != "Check"
|
216
|
-
checks[index] = "Check"
|
242
|
+
checks[index] = "Check#{s}"
|
217
243
|
end
|
218
244
|
end
|
219
245
|
|
@@ -224,7 +250,7 @@ module Brakeman::Options
|
|
224
250
|
opts.on "-x", "--except Check1,Check2,etc", Array, "Skip the specified checks" do |skip|
|
225
251
|
skip.each do |s|
|
226
252
|
if s[0,5] != "Check"
|
227
|
-
s = "Check"
|
253
|
+
s = "Check#{s}"
|
228
254
|
end
|
229
255
|
|
230
256
|
options[:skip_checks] ||= Set.new
|
@@ -254,7 +280,7 @@ module Brakeman::Options
|
|
254
280
|
"Specify output formats. Default is text" do |type|
|
255
281
|
|
256
282
|
type = "s" if type == :text
|
257
|
-
options[:output_format] =
|
283
|
+
options[:output_format] = :"to_#{type}"
|
258
284
|
end
|
259
285
|
|
260
286
|
opts.on "--css-file CSSFile", "Specify CSS to use for HTML output" do |file|
|
@@ -269,6 +295,10 @@ module Brakeman::Options
|
|
269
295
|
options[:interactive_ignore] = true
|
270
296
|
end
|
271
297
|
|
298
|
+
opts.on "--show-ignored", "Show files that are usually ignored by the ignore configuration file" do
|
299
|
+
options[:show_ignored] = true
|
300
|
+
end
|
301
|
+
|
272
302
|
opts.on "-l", "--[no-]combine-locations", "Combine warning locations (Default)" do |combine|
|
273
303
|
options[:combine_locations] = combine
|
274
304
|
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Brakeman::ErubisPatch
|
2
|
+
# Simple patch to make `erubis` compatible with frozen string literals
|
3
|
+
def convert(input)
|
4
|
+
codebuf = +"" # Modified line, the rest is identitical
|
5
|
+
@preamble.nil? ? add_preamble(codebuf) : (@preamble && (codebuf << @preamble))
|
6
|
+
convert_input(codebuf, input)
|
7
|
+
@postamble.nil? ? add_postamble(codebuf) : (@postamble && (codebuf << @postamble))
|
8
|
+
@_proc = nil # clear cached proc object
|
9
|
+
return codebuf # or codebuf.join()
|
10
|
+
end
|
11
|
+
end
|
@@ -1,6 +1,9 @@
|
|
1
1
|
Brakeman.load_brakeman_dependency 'erubis'
|
2
2
|
|
3
|
+
require 'brakeman/parsers/erubis_patch'
|
4
|
+
|
3
5
|
#Erubis processor which ignores any output which is plain text.
|
4
6
|
class Brakeman::ScannerErubis < Erubis::Eruby
|
5
7
|
include Erubis::NoTextEnhancer
|
8
|
+
include Brakeman::ErubisPatch
|
6
9
|
end
|
@@ -1,7 +1,11 @@
|
|
1
1
|
Brakeman.load_brakeman_dependency 'erubis'
|
2
2
|
|
3
|
+
require 'brakeman/parsers/erubis_patch'
|
4
|
+
|
3
5
|
#This is from the rails_xss plugin for Rails 2
|
4
6
|
class Brakeman::Rails2XSSPluginErubis < ::Erubis::Eruby
|
7
|
+
include Brakeman::ErubisPatch
|
8
|
+
|
5
9
|
def add_preamble(src)
|
6
10
|
#src << "@output_buffer = ActiveSupport::SafeBuffer.new;"
|
7
11
|
end
|
@@ -1,11 +1,15 @@
|
|
1
1
|
Brakeman.load_brakeman_dependency 'erubis'
|
2
2
|
|
3
|
+
require 'brakeman/parsers/erubis_patch'
|
4
|
+
|
3
5
|
# This is from Rails 5 version of the Erubis handler
|
4
6
|
# https://github.com/rails/rails/blob/ec608107801b1e505db03ba76bae4a326a5804ca/actionview/lib/action_view/template/handlers/erb.rb#L7-L73
|
5
7
|
class Brakeman::Rails3Erubis < ::Erubis::Eruby
|
8
|
+
include Brakeman::ErubisPatch
|
6
9
|
|
7
10
|
def add_preamble(src)
|
8
11
|
@newline_pending = 0
|
12
|
+
src << "_this_is_to_make_yields_syntactally_correct {"
|
9
13
|
src << "@output_buffer = output_buffer || ActionView::OutputBuffer.new;"
|
10
14
|
end
|
11
15
|
|
@@ -62,7 +66,7 @@ class Brakeman::Rails3Erubis < ::Erubis::Eruby
|
|
62
66
|
|
63
67
|
def add_postamble(src)
|
64
68
|
flush_newline_if_pending(src)
|
65
|
-
src << '@output_buffer.to_s'
|
69
|
+
src << '@output_buffer.to_s; }'
|
66
70
|
end
|
67
71
|
|
68
72
|
def flush_newline_if_pending(src)
|
@@ -2,6 +2,7 @@
|
|
2
2
|
module Slim
|
3
3
|
class Embedded
|
4
4
|
class TiltEngine
|
5
|
+
alias_method :on_slim_embedded, :on_slim_embedded # silence redefined method warning
|
5
6
|
def on_slim_embedded(engine, body, attrs)
|
6
7
|
# Override this method to avoid Slim trying to load sass/scss and failing
|
7
8
|
case engine
|
@@ -22,6 +23,7 @@ module Slim
|
|
22
23
|
class SassEngine
|
23
24
|
protected
|
24
25
|
|
26
|
+
alias_method :tilt_render, :tilt_render # silence redefined method warning
|
25
27
|
def tilt_render(tilt_engine, tilt_options, text)
|
26
28
|
[:dynamic,
|
27
29
|
"BrakemanFilter.render(#{text.inspect}, #{self.class})"]
|
@@ -32,6 +32,7 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
|
|
32
32
|
@or_depth_limit = (tracker && tracker.options[:branch_limit]) || 5 #arbitrary default
|
33
33
|
@meth_env = nil
|
34
34
|
@current_file = current_file
|
35
|
+
@mass_limit = (tracker && tracker.options[:mass_limit]) || 1000 # arbitrary default
|
35
36
|
set_env_defaults
|
36
37
|
end
|
37
38
|
|
@@ -82,8 +83,12 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
|
|
82
83
|
def replace exp, int = 0
|
83
84
|
return exp if int > 3
|
84
85
|
|
85
|
-
if replacement = env[exp]
|
86
|
-
|
86
|
+
if replacement = env[exp]
|
87
|
+
if not duplicate? replacement and replacement.mass < @mass_limit
|
88
|
+
replace(replacement.deep_clone(exp.line), int + 1)
|
89
|
+
else
|
90
|
+
exp
|
91
|
+
end
|
87
92
|
elsif tracker and replacement = tracker.constant_lookup(exp) and not duplicate? replacement
|
88
93
|
replace(replacement.deep_clone(exp.line), int + 1)
|
89
94
|
else
|
@@ -368,7 +373,7 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
|
|
368
373
|
result << join_item(array.last, nil)
|
369
374
|
|
370
375
|
# Combine the strings at the beginning because that's what RubyParser does
|
371
|
-
combined_first = ""
|
376
|
+
combined_first = +""
|
372
377
|
result.each do |e|
|
373
378
|
if string? e
|
374
379
|
combined_first << e.value
|
@@ -660,7 +665,7 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
|
|
660
665
|
exp[2] = exp[2][1]
|
661
666
|
end
|
662
667
|
|
663
|
-
unless array? exp[1] and array? exp[2]
|
668
|
+
unless array? exp[1] and array? exp[2]
|
664
669
|
return process_default(exp)
|
665
670
|
end
|
666
671
|
|
@@ -673,21 +678,42 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
|
|
673
678
|
# Call each assignment as if it is normal
|
674
679
|
vars.each_with_index do |var, i|
|
675
680
|
val = vals[i]
|
676
|
-
if
|
681
|
+
next unless val # TODO: Break if there are no vals left?
|
682
|
+
|
683
|
+
# This happens with nested destructuring like
|
684
|
+
# x, (a, b) = blah
|
685
|
+
if node_type? var, :masgn
|
686
|
+
# Need to add value to masgn exp
|
687
|
+
m = var.dup
|
688
|
+
m[2] = s(:to_ary, val)
|
677
689
|
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
690
|
+
process_masgn m
|
691
|
+
elsif node_type? var, :splat
|
692
|
+
# Assign the rest of the values to the variable:
|
693
|
+
#
|
694
|
+
# a, *b = 1, 2, 3
|
695
|
+
#
|
696
|
+
# b == [2, 3]
|
684
697
|
|
685
|
-
|
698
|
+
|
699
|
+
assign = var[1].dup # var is s(:splat, s(:lasgn, :b))
|
700
|
+
|
701
|
+
if i == vars.length - 1 # Last variable being assigned, slurp up the rest
|
702
|
+
assign.rhs = s(:array, *vals[i..]) # val is the "rest" of the values
|
686
703
|
else
|
687
|
-
assign
|
688
|
-
|
689
|
-
|
704
|
+
# Calculate how many values to assign based on how many variables
|
705
|
+
# there are.
|
706
|
+
#
|
707
|
+
# If there are more values than variables, the splat gets an empty array.
|
708
|
+
|
709
|
+
assign.rhs = s(:array, *vals[i, (vals.length - vars.length + 1)]).line(vals.line)
|
690
710
|
end
|
711
|
+
|
712
|
+
process assign
|
713
|
+
else
|
714
|
+
assign = var.dup
|
715
|
+
assign.rhs = val
|
716
|
+
process assign
|
691
717
|
end
|
692
718
|
end
|
693
719
|
|
@@ -52,7 +52,7 @@ module Brakeman
|
|
52
52
|
def page_via_less text
|
53
53
|
# Adapted from https://github.com/piotrmurach/tty-pager/
|
54
54
|
|
55
|
-
write_io =
|
55
|
+
write_io = IO.popen("less #{less_options.join}", 'w')
|
56
56
|
pid = write_io.pid
|
57
57
|
|
58
58
|
write_io.write(text)
|
@@ -27,7 +27,7 @@ class Brakeman::Report::Markdown < Brakeman::Report::Table
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def generate_report
|
30
|
-
out = "# BRAKEMAN REPORT\n\n" <<
|
30
|
+
out = +"# BRAKEMAN REPORT\n\n" <<
|
31
31
|
generate_metadata.to_s << "\n\n" <<
|
32
32
|
generate_checks.to_s << "\n\n" <<
|
33
33
|
"### SUMMARY\n\n" <<
|
@@ -8,7 +8,7 @@ class Brakeman::Report::Table < Brakeman::Report::Base
|
|
8
8
|
|
9
9
|
def generate_report
|
10
10
|
summary_option = tracker.options[:summary_only]
|
11
|
-
out = ""
|
11
|
+
out = +""
|
12
12
|
|
13
13
|
unless summary_option == :no_summary
|
14
14
|
out << text_header <<
|
@@ -166,7 +166,7 @@ class Brakeman::Report::Table < Brakeman::Report::Base
|
|
166
166
|
|
167
167
|
template_rows = template_rows.sort_by{|name, value| name.to_s}
|
168
168
|
|
169
|
-
output = ''
|
169
|
+
output = +''
|
170
170
|
template_rows.each do |template|
|
171
171
|
output << template.first.to_s << "\n\n"
|
172
172
|
table = @table.new(:headings => ['Output']) do |t|
|
@@ -9,7 +9,6 @@ class Brakeman::Report::Tabs < Brakeman::Report::Table
|
|
9
9
|
|
10
10
|
self.send(meth).map do |w|
|
11
11
|
line = w.line || 0
|
12
|
-
w.warning_type.gsub!(/[^\w\s]/, ' ')
|
13
12
|
"#{(w.file.absolute)}\t#{line}\t#{w.warning_type}\t#{category}\t#{w.format_message}\t#{w.confidence_name}"
|
14
13
|
end.join "\n"
|
15
14
|
|
@@ -4,7 +4,7 @@ class Brakeman::Report::Text < Brakeman::Report::Base
|
|
4
4
|
def generate_report
|
5
5
|
HighLine.use_color = !!tracker.options[:output_color]
|
6
6
|
summary_option = tracker.options[:summary_only]
|
7
|
-
@output_string = "\n"
|
7
|
+
@output_string = +"\n"
|
8
8
|
|
9
9
|
unless summary_option == :no_summary
|
10
10
|
add_chunk generate_header
|
@@ -21,6 +21,9 @@ class Brakeman::Report::Text < Brakeman::Report::Base
|
|
21
21
|
add_chunk generate_obsolete
|
22
22
|
add_chunk generate_errors
|
23
23
|
add_chunk generate_warnings
|
24
|
+
add_chunk generate_show_ignored_overview if tracker.options[:show_ignored] && ignored_warnings.any?
|
25
|
+
|
26
|
+
@output_string
|
24
27
|
end
|
25
28
|
|
26
29
|
def add_chunk chunk, out = @output_string
|
@@ -101,6 +104,10 @@ class Brakeman::Report::Text < Brakeman::Report::Base
|
|
101
104
|
end
|
102
105
|
end
|
103
106
|
|
107
|
+
def generate_show_ignored_overview
|
108
|
+
double_space("Ignored Warnings", ignored_warnings.map {|w| output_warning w})
|
109
|
+
end
|
110
|
+
|
104
111
|
def generate_errors
|
105
112
|
return if tracker.errors.empty?
|
106
113
|
full_trace = tracker.options[:debug]
|
data/lib/brakeman/scanner.rb
CHANGED
@@ -125,7 +125,7 @@ class Brakeman::Scanner
|
|
125
125
|
end
|
126
126
|
|
127
127
|
def parse_files
|
128
|
-
fp = Brakeman::FileParser.new(tracker.app_tree, tracker.options[:parser_timeout], tracker.options[:parallel_checks])
|
128
|
+
fp = Brakeman::FileParser.new(tracker.app_tree, tracker.options[:parser_timeout], tracker.options[:parallel_checks], tracker.options[:use_prism])
|
129
129
|
|
130
130
|
fp.parse_files tracker.app_tree.ruby_file_paths
|
131
131
|
|
@@ -414,7 +414,7 @@ class Brakeman::Scanner
|
|
414
414
|
end
|
415
415
|
|
416
416
|
def parse_ruby_file file
|
417
|
-
fp = Brakeman::FileParser.new(tracker.app_tree, tracker.options[:parser_timeout])
|
417
|
+
fp = Brakeman::FileParser.new(tracker.app_tree, tracker.options[:parser_timeout], false, tracker.options[:use_prism])
|
418
418
|
fp.parse_ruby(file.read, file)
|
419
419
|
rescue Exception => e
|
420
420
|
tracker.error(e)
|
@@ -111,6 +111,14 @@ module Brakeman
|
|
111
111
|
tracker.options[:rails6] = true
|
112
112
|
tracker.options[:rails7] = true
|
113
113
|
Brakeman.notify "[Notice] Detected Rails 7 application"
|
114
|
+
elsif @rails_version.start_with? "8"
|
115
|
+
tracker.options[:rails3] = true
|
116
|
+
tracker.options[:rails4] = true
|
117
|
+
tracker.options[:rails5] = true
|
118
|
+
tracker.options[:rails6] = true
|
119
|
+
tracker.options[:rails7] = true
|
120
|
+
tracker.options[:rails8] = true
|
121
|
+
Brakeman.notify "[Notice] Detected Rails 8 application"
|
114
122
|
end
|
115
123
|
end
|
116
124
|
end
|
@@ -193,7 +201,7 @@ module Brakeman
|
|
193
201
|
|
194
202
|
version = tracker.config.rails[:load_defaults].value.to_s
|
195
203
|
|
196
|
-
unless version.match?
|
204
|
+
unless version.match?(/^\d+\.\d+$/)
|
197
205
|
Brakeman.debug "[Notice] Unknown version: #{tracker.config.rails[:load_defaults]}"
|
198
206
|
return
|
199
207
|
end
|
data/lib/brakeman/util.rb
CHANGED
@@ -63,14 +63,12 @@ module Brakeman::Util
|
|
63
63
|
case exp
|
64
64
|
when Sexp
|
65
65
|
case exp.node_type
|
66
|
-
when :const
|
66
|
+
when :const, :colon3
|
67
67
|
exp.value
|
68
68
|
when :lvar
|
69
69
|
exp.value.to_sym
|
70
70
|
when :colon2
|
71
71
|
"#{class_name(exp.lhs)}::#{exp.rhs}".to_sym
|
72
|
-
when :colon3
|
73
|
-
"::#{exp.value}".to_sym
|
74
72
|
when :self
|
75
73
|
@current_class || @current_module || nil
|
76
74
|
else
|
data/lib/brakeman/version.rb
CHANGED
data/lib/brakeman/warning.rb
CHANGED
@@ -317,7 +317,7 @@ class Brakeman::Warning
|
|
317
317
|
|
318
318
|
def format_ruby code, strip
|
319
319
|
formatted = Brakeman::OutputProcessor.new.format(code)
|
320
|
-
formatted.gsub
|
320
|
+
formatted = formatted.gsub(/(\t|\r|\n)+/, " ") if strip
|
321
321
|
formatted
|
322
322
|
end
|
323
323
|
end
|
data/lib/brakeman.rb
CHANGED
@@ -65,6 +65,7 @@ module Brakeman
|
|
65
65
|
# * :report_routes - show found routes on controllers (default: false)
|
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
|
+
# * :show_ignored - Display warnings that are usually ignored
|
68
69
|
# * :sql_safe_methods - array of sql sanitization methods to consider safe
|
69
70
|
# * :skip_libs - do not process lib/ directory (default: false)
|
70
71
|
# * :skip_vendor - do not process vendor/ directory (default: true)
|
@@ -128,9 +129,8 @@ module Brakeman
|
|
128
129
|
|
129
130
|
#Load configuration file
|
130
131
|
if config = config_file(custom_location, app_path)
|
131
|
-
require '
|
132
|
-
|
133
|
-
options = SafeYAML.load_file config, :deserialize_symbols => true
|
132
|
+
require 'yaml'
|
133
|
+
options = YAML.safe_load_file config, permitted_classes: [Symbol], symbolize_names: true
|
134
134
|
|
135
135
|
if options
|
136
136
|
options.each { |k, v| options[k] = Set.new v if v.is_a? Array }
|
@@ -199,6 +199,7 @@ module Brakeman
|
|
199
199
|
:relative_path => false,
|
200
200
|
:report_progress => true,
|
201
201
|
:safe_methods => Set.new,
|
202
|
+
:show_ignored => false,
|
202
203
|
:sql_safe_methods => Set.new,
|
203
204
|
:skip_checks => Set.new,
|
204
205
|
:skip_vendor => true,
|
data/lib/ruby_parser/bm_sexp.rb
CHANGED
@@ -6,6 +6,7 @@ class Sexp
|
|
6
6
|
ASSIGNMENT_BOOL = [:gasgn, :iasgn, :lasgn, :cvdecl, :cvasgn, :cdecl, :or, :and, :colon2, :op_asgn_or]
|
7
7
|
CALLS = [:call, :attrasgn, :safe_call, :safe_attrasgn]
|
8
8
|
|
9
|
+
alias_method :method_missing, :method_missing # silence redefined method warning
|
9
10
|
def method_missing name, *args
|
10
11
|
#Brakeman does not use this functionality,
|
11
12
|
#so overriding it to raise a NoMethodError.
|
@@ -46,10 +47,12 @@ class Sexp
|
|
46
47
|
s
|
47
48
|
end
|
48
49
|
|
50
|
+
alias_method :paren, :paren # silence redefined method warning
|
49
51
|
def paren
|
50
52
|
@paren ||= false
|
51
53
|
end
|
52
54
|
|
55
|
+
alias_method :value, :value # silence redefined method warning
|
53
56
|
def value
|
54
57
|
raise WrongSexpError, "Sexp#value called on multi-item Sexp: `#{self.inspect}`" if size > 2
|
55
58
|
self[1]
|
@@ -98,6 +101,7 @@ class Sexp
|
|
98
101
|
old_push arg
|
99
102
|
end
|
100
103
|
|
104
|
+
alias_method :hash, :hash # silence redefined method warning
|
101
105
|
def hash
|
102
106
|
#There still seems to be some instances in which the hash of the
|
103
107
|
#Sexp changes, but I have not found what method call is doing it.
|
@@ -616,7 +620,7 @@ end
|
|
616
620
|
|
617
621
|
#Invalidate hash cache if the Sexp changes
|
618
622
|
[:[]=, :clear, :collect!, :compact!, :concat, :delete, :delete_at,
|
619
|
-
:delete_if, :drop, :drop_while, :fill, :flatten!, :
|
623
|
+
:delete_if, :drop, :drop_while, :fill, :flatten!, :insert,
|
620
624
|
:keep_if, :map!, :pop, :push, :reject!, :replace, :reverse!, :rotate!,
|
621
625
|
:select!, :shift, :shuffle!, :slice!, :sort!, :sort_by!, :transpose,
|
622
626
|
:uniq!, :unshift].each do |method|
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: brakeman-min
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.
|
4
|
+
version: 6.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin Collins
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-08-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: csv
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: minitest
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,28 +128,14 @@ dependencies:
|
|
114
128
|
requirements:
|
115
129
|
- - "~>"
|
116
130
|
- !ruby/object:Gem::Version
|
117
|
-
version: 2.
|
131
|
+
version: 2.5.1
|
118
132
|
type: :runtime
|
119
133
|
prerelease: false
|
120
134
|
version_requirements: !ruby/object:Gem::Requirement
|
121
135
|
requirements:
|
122
136
|
- - "~>"
|
123
137
|
- !ruby/object:Gem::Version
|
124
|
-
version: 2.
|
125
|
-
- !ruby/object:Gem::Dependency
|
126
|
-
name: safe_yaml
|
127
|
-
requirement: !ruby/object:Gem::Requirement
|
128
|
-
requirements:
|
129
|
-
- - ">="
|
130
|
-
- !ruby/object:Gem::Version
|
131
|
-
version: '1.0'
|
132
|
-
type: :runtime
|
133
|
-
prerelease: false
|
134
|
-
version_requirements: !ruby/object:Gem::Requirement
|
135
|
-
requirements:
|
136
|
-
- - ">="
|
137
|
-
- !ruby/object:Gem::Version
|
138
|
-
version: '1.0'
|
138
|
+
version: 2.5.1
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
140
|
name: racc
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
@@ -262,6 +262,7 @@ files:
|
|
262
262
|
- lib/brakeman/format/style.css
|
263
263
|
- lib/brakeman/messages.rb
|
264
264
|
- lib/brakeman/options.rb
|
265
|
+
- lib/brakeman/parsers/erubis_patch.rb
|
265
266
|
- lib/brakeman/parsers/haml_embedded.rb
|
266
267
|
- lib/brakeman/parsers/rails2_erubis.rb
|
267
268
|
- lib/brakeman/parsers/rails2_xss_plugin_erubis.rb
|
@@ -376,7 +377,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
376
377
|
- !ruby/object:Gem::Version
|
377
378
|
version: '0'
|
378
379
|
requirements: []
|
379
|
-
rubygems_version: 3.
|
380
|
+
rubygems_version: 3.3.27
|
380
381
|
signing_key:
|
381
382
|
specification_version: 4
|
382
383
|
summary: Security vulnerability scanner for Ruby on Rails.
|