brakeman 8.0.2 → 8.0.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 408455132c50dab2b913428c4532b12e5ef60cd3343935a1b505c8b539b2d5e6
4
- data.tar.gz: 86e837f136df2a3916b4288c0f32191b0ac2379b0b90a73286fa0cf2d0aca714
3
+ metadata.gz: 90b39cd822319fe03d9a0b331239d2ed8fbcfe2db659761d3f0273b3a48e4116
4
+ data.tar.gz: aff94e8cefaa7e8d54aa8a5d7f9a3c0a9bb532ac758e8c3bd7acd2c30df5c6ee
5
5
  SHA512:
6
- metadata.gz: c56c3b0598eade85878e6004b49cc6eb5ecc7be6bd011a7d11c1b462192c161d6afc38e2d50b2c088aba0a4ab55c89b4f01d740e6dbf4d84e2276c9cab541415
7
- data.tar.gz: b08b76a3d45559215cf5a9d288f9561d25dccd233803346d0a783c36decb9ebba4b8e2c665775cee21fc31b6a60126fb79ea9c98ffdc4d24c9eb2502abfab401
6
+ metadata.gz: c2f00398efaf4e652a4ae1034facdaa28169a852ebef8464e5723fcd328dba1fb08d8e7b1c75d639f5d7127046eb1aa296d0f1a38d1e563180b59596aa3d5437
7
+ data.tar.gz: f8131d641b70c662017e6918f669825cc62c766325ac124dee4210dd2fd4a42bb892ef901d4f12dd7245043fb84539694f6de7badf996c19c0f7aa63e27a83c6
data/CHANGES.md CHANGED
@@ -1,3 +1,24 @@
1
+ # 8.0.5 - 2026-06-12
2
+
3
+ * Add `quote_schema_name` to safe quote method list (Zsolt Kozaroczy)
4
+ * Fix SQL injection false positive for `compact_blank`/`compact` on permitted params (Arpit Jain)
5
+ * Fix inline render false positive for local named `text` (Arpit Jain)
6
+ * Fix HAML crash on `.raw` calls (Federico Franco)
7
+ * Fix Ruby version parsing - especially for non-CRuby versions (Chris Southerland Jr)
8
+ * Fix `TemplateAliasProcessor#template_name` arity (viralpraxis)
9
+ * Reduce false positives when using shell escaping
10
+
11
+ # 8.0.4 - 2026-02-26
12
+
13
+ * Load 'date' library for `--ensure-latest`
14
+
15
+ # 8.0.3 - 2026-02-26
16
+
17
+ * Fix `polymorphic_name` SQLi false positive (Fredrico Franco)
18
+ * Fix logger behavior when loading config files
19
+ * Handle application names with module prefixes
20
+ * Add release age option for `--ensure-latest`
21
+
1
22
  # 8.0.2 - 2026-02-03
2
23
 
3
24
  * Reline console control should use stderr
data/bundle/load.rb CHANGED
@@ -3,7 +3,7 @@ $:.unshift "#{path}/bundle/ruby/3.2.0/gems/csv-3.3.5/lib"
3
3
  $:.unshift "#{path}/bundle/ruby/3.2.0/gems/erubi-1.13.1/lib"
4
4
  $:.unshift "#{path}/bundle/ruby/3.2.0/gems/haml-6.4.0/lib"
5
5
  $:.unshift "#{path}/bundle/ruby/3.2.0/gems/highline-3.1.2/lib"
6
- $:.unshift "#{path}/bundle/ruby/3.2.0/gems/parallel-1.27.0/lib"
6
+ $:.unshift "#{path}/bundle/ruby/3.2.0/gems/parallel-1.28.0/lib"
7
7
  $:.unshift "#{path}/bundle/ruby/3.2.0/gems/reline-0.6.3/lib"
8
8
  $:.unshift "#{path}/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib"
9
9
  $:.unshift "#{path}/bundle/ruby/3.2.0/gems/ruby2ruby-2.5.2/lib"
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+ module Parallel
3
+ VERSION = Version = '1.28.0' # rubocop:disable Naming/ConstantName
4
+ end
@@ -15,6 +15,17 @@ module Parallel
15
15
  super()
16
16
  @value = value
17
17
  end
18
+
19
+ # marshal_dump that is used for ruby exceptions
20
+ # avoid dumping the cause since nobody needs that and it can include undumpable exceptions
21
+ def _dump(_depth)
22
+ Marshal.dump(@value)
23
+ end
24
+
25
+ # marshal_load that is used for ruby exceptions
26
+ def self._load(data)
27
+ new(Marshal.load(data))
28
+ end
18
29
  end
19
30
 
20
31
  class Kill < Break
@@ -122,9 +122,14 @@ class Brakeman::CheckExecute < Brakeman::BaseCheck
122
122
  # should be ignored
123
123
 
124
124
  args.pop if hash?(args.last) && args.length > 2
125
- failure = include_user_input?(args) ||
126
- dangerous_interp?(args) ||
127
- dangerous_string_building?(args)
125
+
126
+ args.each_sexp do |arg|
127
+ failure = include_user_input?(arg) ||
128
+ dangerous_interp?(arg) ||
129
+ dangerous_string_building?(arg)
130
+
131
+ break if failure
132
+ end
128
133
  else
129
134
  failure = include_user_input?(args) ||
130
135
  dangerous_interp?(args) ||
@@ -176,6 +181,8 @@ class Brakeman::CheckExecute < Brakeman::BaseCheck
176
181
  def include_user_input? exp
177
182
  if node_type? exp, :arglist, :dstr, :evstr, :dxstr
178
183
  exp.each_sexp do |e|
184
+ next if shell_escape? e
185
+
179
186
  if res = include_user_input?(e)
180
187
  return res
181
188
  end
@@ -196,7 +203,7 @@ class Brakeman::CheckExecute < Brakeman::BaseCheck
196
203
  # Check for input at start of string
197
204
  exp[1] == "" and
198
205
  node_type? exp[2], :evstr and
199
- has_immediate_user_input? exp[2]
206
+ dangerous? exp[2]
200
207
  else
201
208
  has_immediate_user_input? exp
202
209
  end
@@ -266,6 +273,8 @@ class Brakeman::CheckExecute < Brakeman::BaseCheck
266
273
  end
267
274
 
268
275
  def dangerous_interp? exp
276
+ return if shell_escape? exp
277
+
269
278
  match = include_interp? exp
270
279
  return unless match
271
280
  interp = match.match
@@ -311,7 +311,7 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
311
311
  end
312
312
 
313
313
  if request_value? arg
314
- unless call? arg and params? arg.target and [:permit, :slice, :to_h, :to_hash, :symbolize_keys].include? arg.method
314
+ unless call? arg and params? arg.target and [:permit, :slice, :to_h, :to_hash, :symbolize_keys, :compact, :compact_blank].include? arg.method
315
315
  # Model.where(params[:where])
316
316
  arg
317
317
  end
@@ -600,7 +600,8 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
600
600
  :sanitize_sql_for_assignment, :sanitize_sql_for_conditions, :sanitize_sql_hash,
601
601
  :sanitize_sql_hash_for_assignment, :sanitize_sql_hash_for_conditions,
602
602
  :to_sql, :sanitize, :primary_key, :table_name_prefix, :table_name_suffix,
603
- :where_values_hash, :foreign_key, :uuid, :escape, :escape_string
603
+ :where_values_hash, :foreign_key, :uuid, :escape, :escape_string,
604
+ :polymorphic_name
604
605
  ]
605
606
 
606
607
  def ignore_methods_in_sql
@@ -644,7 +645,7 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
644
645
  locale_call? exp
645
646
  end
646
647
 
647
- QUOTE_METHODS = [:quote, :quote_column_name, :quoted_date, :quote_string, :quote_table_name]
648
+ QUOTE_METHODS = [:quote, :quote_column_name, :quoted_date, :quote_string, :quote_table_name, :quote_schema_name]
648
649
 
649
650
  def quote_call? exp
650
651
  if call? exp.target
@@ -31,7 +31,7 @@ module Brakeman
31
31
  set_interrupt_handler options
32
32
  early_exit_options options
33
33
  set_options options, default_app_path
34
- check_latest if options[:ensure_latest]
34
+ check_latest(options[:ensure_latest]) if options[:ensure_latest]
35
35
  run_report options
36
36
 
37
37
  quit
@@ -39,9 +39,14 @@ module Brakeman
39
39
 
40
40
  # Check for the latest version.
41
41
  #
42
- # If the latest version is newer, quit with a message.
43
- def check_latest
44
- if error = Brakeman.ensure_latest
42
+ # If the latest version is newer than the current version
43
+ # and age, exit.
44
+ def check_latest(days_old = 0)
45
+ if days_old == true
46
+ days_old = 0
47
+ end
48
+
49
+ if error = Brakeman.ensure_latest(days_old:)
45
50
  quit Brakeman::Not_Latest_Version_Exit_Code, error
46
51
  end
47
52
  end
@@ -63,8 +63,12 @@ module Brakeman::Options
63
63
  options[:exit_on_error] = exit_on_error
64
64
  end
65
65
 
66
- opts.on "--ensure-latest", "Fail when Brakeman is outdated" do
67
- options[:ensure_latest] = true
66
+ opts.on "--ensure-latest [DAYS]", Integer, "Fail when Brakeman is outdated. Optionally set minimum age in days." do |days|
67
+ if days and not (1..15).include? days
68
+ raise OptionParser::InvalidArgument
69
+ end
70
+
71
+ options[:ensure_latest] = days || true
68
72
  end
69
73
 
70
74
  opts.on "--ensure-ignore-notes", "Fail when an ignored warnings does not include a note" do
@@ -258,12 +258,19 @@ class Brakeman::BaseProcessor < Brakeman::SexpProcessor
258
258
  #Look for "type" of render in options hash
259
259
  #For example, render :file => "blah"
260
260
  if hash? last_arg
261
- hash_iterate(last_arg) do |key, val|
262
- if symbol? key and types_in_hash.include? key.value
263
- type = key.value
264
- value = val
265
- else
266
- rest << key << val
261
+ if type
262
+ #The render type was already determined by a positional argument, so a
263
+ #key in the options hash that happens to match a render type name (e.g.
264
+ #`text:`) is a local passed to the partial/action, not a type directive.
265
+ rest = last_arg
266
+ else
267
+ hash_iterate(last_arg) do |key, val|
268
+ if symbol? key and types_in_hash.include? key.value
269
+ type = key.value
270
+ value = val
271
+ else
272
+ rest << key << val
273
+ end
267
274
  end
268
275
  end
269
276
  end
@@ -6,7 +6,7 @@ class Brakeman::GemProcessor < Brakeman::BasicProcessor
6
6
  def initialize *args
7
7
  super
8
8
  @gem_name_version = /^\s*([-_+.A-Za-z0-9]+) \((\w(\.\w+)*)\)/
9
- @ruby_version = /^\s+ruby (\d\.\d.\d+)/
9
+ @ruby_version = /^\s+ruby (\d+\.\d+\.\d+)/
10
10
  end
11
11
 
12
12
  def process_gems gem_files
@@ -186,6 +186,8 @@ class Brakeman::HamlTemplateProcessor < Brakeman::TemplateProcessor
186
186
 
187
187
  def raw? exp
188
188
  call? exp and
189
- exp.method == :raw
189
+ exp.target.nil? and
190
+ exp.method == :raw and
191
+ exp.first_arg
190
192
  end
191
193
  end
@@ -17,6 +17,7 @@ require 'brakeman/processors/lib/basic_processor'
17
17
  #Values for tracker.config.rails will still be Sexps.
18
18
  class Brakeman::Rails3ConfigProcessor < Brakeman::BasicProcessor
19
19
  RAILS_CONFIG = Sexp.new(:call, nil, :config)
20
+ RAILS_APPLICATION = Sexp.new(:colon2, s(:const, :Rails), :Application)
20
21
 
21
22
  def initialize *args
22
23
  super
@@ -48,7 +49,7 @@ class Brakeman::Rails3ConfigProcessor < Brakeman::BasicProcessor
48
49
 
49
50
  #Look for class Application < Rails::Application
50
51
  def process_class exp
51
- if exp.class_name == :Application
52
+ if application_class? exp
52
53
  @inside_config = true
53
54
  process_all exp.body if sexp? exp.body
54
55
  @inside_config = false
@@ -57,6 +58,14 @@ class Brakeman::Rails3ConfigProcessor < Brakeman::BasicProcessor
57
58
  exp
58
59
  end
59
60
 
61
+ def application_class? exp
62
+ return unless node_type? exp, :class
63
+
64
+ exp.class_name == :Application or
65
+ (node_type? exp.class_name, :colon2 and exp.class_name.rhs == :Application) or
66
+ (exp.parent_name == RAILS_APPLICATION)
67
+ end
68
+
60
69
  #Look for configuration settings that
61
70
  #are just a call like
62
71
  #
@@ -19,7 +19,9 @@ module Brakeman::RenderHelper
19
19
  end
20
20
  when :default
21
21
  begin
22
- process_template template_name, exp[3], nil, exp.line
22
+ # exp[2] is either the action name (from controller) or :default when no explicit arg
23
+ name_arg = (exp[2].nil? || exp[2] == :default) ? nil : exp[2]
24
+ process_template template_name(name_arg), exp[3], nil, exp.line
23
25
  rescue ArgumentError
24
26
  Brakeman.debug "Problem processing render: #{exp}"
25
27
  end
@@ -187,8 +187,14 @@ class Brakeman::Scanner
187
187
  end
188
188
 
189
189
  if @app_tree.exists? ".ruby-version"
190
- if version = @app_tree.file_path(".ruby-version").read[/(\d\.\d.\d+)/]
191
- tracker.config.set_ruby_version version, @app_tree.file_path(".ruby-version"), 1
190
+ contents = @app_tree.file_path(".ruby-version").read
191
+ # Skip alternative Ruby implementations — the EOL dates Brakeman knows
192
+ # about are MRI's, so a `.ruby-version` of "jruby-10.0.2.0" should not
193
+ # be parsed as MRI 0.0.2 / 10.0.2.
194
+ unless contents =~ /\A\s*(jruby|truffleruby|rbx|rubinius|mruby)\b/i
195
+ if version = contents[/(\d+\.\d+\.\d+)/]
196
+ tracker.config.set_ruby_version version, @app_tree.file_path(".ruby-version"), 1
197
+ end
192
198
  end
193
199
  end
194
200
 
@@ -1,3 +1,3 @@
1
1
  module Brakeman
2
- Version = "8.0.2"
2
+ Version = "8.0.5"
3
3
  end
data/lib/brakeman.rb CHANGED
@@ -167,7 +167,6 @@ module Brakeman
167
167
  #Load options from YAML file
168
168
  def self.load_options line_options
169
169
  custom_location = line_options[:config_file]
170
- quiet = line_options[:quiet]
171
170
  app_path = line_options[:app_path]
172
171
 
173
172
  #Load configuration file
@@ -175,29 +174,28 @@ module Brakeman
175
174
  require 'yaml'
176
175
  options = YAML.safe_load_file config, permitted_classes: [Symbol], symbolize_names: true
177
176
 
178
- # Brakeman.logger is probably not set yet
179
- logger = Brakeman::Logger.get_logger(options || line_options)
180
-
181
177
  if options
182
178
  options.each { |k, v| options[k] = Set.new v if v.is_a? Array }
183
179
 
184
180
  # After parsing the yaml config file for options, convert any string keys into symbols.
185
181
  options.keys.select {|k| k.is_a? String}.map {|k| k.to_sym }.each {|k| options[k] = options[k.to_s]; options.delete(k.to_s) }
186
182
 
183
+ # Brakeman.logger is probably not set yet
184
+ logger = Brakeman::Logger.get_logger(options.merge(line_options))
185
+
187
186
  unless line_options[:allow_check_paths_in_config]
188
187
  if options.include? :additional_checks_path
189
188
  options.delete :additional_checks_path
190
189
 
191
- logger.alert 'Ignoring additional check paths in config file. Use --allow-check-paths-in-config to allow' unless (options[:quiet] || quiet)
190
+ logger.alert 'Ignoring additional check paths in config file. Use --allow-check-paths-in-config to allow'
192
191
  end
193
192
  end
194
193
 
195
- # notify if options[:quiet] and quiet is nil||false
196
- # potentially remove these checks now that logger is used
197
- logger.alert "Using configuration in #{config}" unless (options[:quiet] || quiet)
194
+ logger.alert "Using configuration in #{config}"
198
195
  options
199
196
  else
200
- logger.alert "Empty configuration file: #{config}" unless quiet
197
+ logger = Brakeman::Logger.get_logger(line_options)
198
+ logger.alert "Empty configuration file: #{config}"
201
199
  {}
202
200
  end
203
201
  else
@@ -416,11 +414,27 @@ module Brakeman
416
414
  end
417
415
  end
418
416
 
419
- def self.ensure_latest
417
+ # Returns quit message unless the latest version
418
+ # of Brakeman matches the current version.
419
+ #
420
+ # Optionally checks that the latest version is at least
421
+ # the specified number of days old.
422
+ def self.ensure_latest(days_old: 0)
423
+ require 'date'
424
+
420
425
  current = Brakeman::Version
421
- latest = Gem.latest_version_for('brakeman').to_s
422
- if current != latest
423
- "Brakeman #{current} is not the latest version #{latest}"
426
+ latest = Gem.latest_spec_for('brakeman')
427
+ release_date = latest.date.to_date
428
+ latest_version = latest.version.to_s
429
+
430
+ if (Date.today - latest.date.to_date) >= days_old
431
+ if current != latest_version
432
+ return "Brakeman #{current} is not the latest version #{latest_version}"
433
+ else
434
+ false
435
+ end
436
+ else
437
+ false
424
438
  end
425
439
  end
426
440
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brakeman
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.0.2
4
+ version: 8.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Collins
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-02-03 00:00:00.000000000 Z
11
+ date: 2026-06-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: racc
@@ -150,9 +150,9 @@ files:
150
150
  - bundle/ruby/3.2.0/gems/highline-3.1.2/lib/highline/terminal/unix_stty.rb
151
151
  - bundle/ruby/3.2.0/gems/highline-3.1.2/lib/highline/version.rb
152
152
  - bundle/ruby/3.2.0/gems/highline-3.1.2/lib/highline/wrapper.rb
153
- - bundle/ruby/3.2.0/gems/parallel-1.27.0/MIT-LICENSE.txt
154
- - bundle/ruby/3.2.0/gems/parallel-1.27.0/lib/parallel.rb
155
- - bundle/ruby/3.2.0/gems/parallel-1.27.0/lib/parallel/version.rb
153
+ - bundle/ruby/3.2.0/gems/parallel-1.28.0/MIT-LICENSE.txt
154
+ - bundle/ruby/3.2.0/gems/parallel-1.28.0/lib/parallel.rb
155
+ - bundle/ruby/3.2.0/gems/parallel-1.28.0/lib/parallel/version.rb
156
156
  - bundle/ruby/3.2.0/gems/reline-0.6.3/BSDL
157
157
  - bundle/ruby/3.2.0/gems/reline-0.6.3/COPYING
158
158
  - bundle/ruby/3.2.0/gems/reline-0.6.3/README.md
@@ -700,7 +700,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
700
700
  - !ruby/object:Gem::Version
701
701
  version: '0'
702
702
  requirements: []
703
- rubygems_version: 3.4.1
703
+ rubygems_version: 3.4.19
704
704
  signing_key:
705
705
  specification_version: 4
706
706
  summary: Security vulnerability scanner for Ruby on Rails.
@@ -1,4 +0,0 @@
1
- # frozen_string_literal: true
2
- module Parallel
3
- VERSION = Version = '1.27.0' # rubocop:disable Naming/ConstantName
4
- end