brakeman-min 8.0.6 → 8.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aadf11175c5a1a59351d414d8983a065482bd293596f8ae1e27e0fd08ba12e38
4
- data.tar.gz: 12d1897319ce9f8b9f7062ba52cda478e7bf3d0708070f7f8a20722a9265e5a3
3
+ metadata.gz: 5617f56b1375fc31177923381488b7a018322e9508712cbb6fcaef3ebb2c8190
4
+ data.tar.gz: 90f1ec8f568eebe6ae6a5f058395dbb035dcd6a5cfaf55b62c3542d398fb693e
5
5
  SHA512:
6
- metadata.gz: bd0e1e83d489c975f98ca1314bb9e4178819227311653797da55ff4d62b650489242abb96a04821e3ebce906a7897d3f68b97140089dfdc3c68fa55df0d77dfb
7
- data.tar.gz: '05594cee81a90105fe78c2104dc6a80bb3e8b56cfdfff0861f1d1b66a1fdcb3ddb0fd64662e87c7eaa4d17c0d3282c45f77268f5d2ea527d45c18836ba778cc1'
6
+ metadata.gz: e129e0b2729108abf747ec6c7b0077d1df3dae70be874e9a037fde99ac582103c42153efd63ba75f0440152af8b7b143eff3ff36682142755edbbd8ad2590741
7
+ data.tar.gz: 58733048687ad8cbac4e17d34e0c92e5d29955d6e72bfc9b80586d46167f082d26d07318946af366a8297e27b7e67eeac5f1620355e243d34d65e605312baf07
data/CHANGES.md CHANGED
@@ -1,3 +1,15 @@
1
+ # 8.1.0 - 2026-09-30
2
+
3
+ * Better help and error message for `--ensure-latest`
4
+ * Fix frozen string error (Shai Coleman)
5
+ * Update Sonar report format (fangxing)
6
+ * Fix frozen `src` string error
7
+ * Recognize `Haml::AttributeBuilder.build_class` as an escaped output (Yuriy Tumanov)
8
+ * Include regex code in validation warnings (Eliot Sykes)
9
+ * Check validation regexes in non-activerecord models (Eliot Sykes)
10
+ * Skip top-level vendor directory before recursive globbing (Conor O'Donnell)
11
+ * Support Rails 7.1+ positional enum syntax in SQL injection check (Michael Vogl/Yuriy Tumanov)
12
+
1
13
  # 8.0.6 - 2026-08-13
2
14
 
3
15
  * Fix EOL date for Rails 8.0 (yeaseul-kim)
@@ -64,6 +64,8 @@ module Brakeman
64
64
  @only_files = init_options[:only_files]
65
65
  @additional_libs_path = init_options[:additional_libs_path] || []
66
66
  @engine_paths = init_options[:engine_paths] || []
67
+ @additional_libs_path_pairs = @additional_libs_path.map { |p| [p, expand_path(p)] }
68
+ @engine_path_pairs = @engine_paths.map { |p| [p, expand_path(p)] }
67
69
  @absolute_engine_paths = @engine_paths.select { |path| path.start_with?(File::SEPARATOR) }
68
70
  @relative_engine_paths = @engine_paths - @absolute_engine_paths
69
71
  @skip_vendor = init_options[:skip_vendor]
@@ -251,7 +253,10 @@ module Brakeman
251
253
  paths.reject do |path|
252
254
  relative_path = path.relative
253
255
 
254
- if @skip_vendor and relative_path.include? 'vendor/' and !in_engine_paths?(path) and !in_add_libs_paths?(path)
256
+ if @skip_vendor and
257
+ (relative_path == 'vendor' || relative_path.include?('vendor/')) and
258
+ !in_engine_paths?(path) and
259
+ !in_add_libs_paths?(path)
255
260
  true
256
261
  else
257
262
  match_path EXCLUDED_PATHS, path
@@ -260,11 +265,17 @@ module Brakeman
260
265
  end
261
266
 
262
267
  def in_engine_paths?(path)
263
- @engine_paths.any? { |p| path.absolute.include?(p) }
268
+ @engine_path_pairs.any? do |original, expanded|
269
+ path.absolute.include?(original) ||
270
+ expanded.start_with?("#{path.absolute}#{File::SEPARATOR}")
271
+ end
264
272
  end
265
273
 
266
274
  def in_add_libs_paths?(path)
267
- @additional_libs_path.any? { |p| path.absolute.include?(p) }
275
+ @additional_libs_path_pairs.any? do |original, expanded|
276
+ path.absolute.include?(original) ||
277
+ expanded.start_with?("#{path.absolute}#{File::SEPARATOR}")
278
+ end
268
279
  end
269
280
 
270
281
  def match_path files, path
@@ -16,7 +16,7 @@ class Brakeman::CheckValidationRegex < Brakeman::BaseCheck
16
16
  FORMAT = Sexp.new(:lit, :format)
17
17
 
18
18
  def run_check
19
- active_record_models.each do |name, model|
19
+ tracker.models.each do |name, model|
20
20
  @current_model = model
21
21
  format_validations = model.options[:validates_format_of]
22
22
 
@@ -92,7 +92,8 @@ class Brakeman::CheckValidationRegex < Brakeman::BaseCheck
92
92
  :message => msg("Insufficient validation for ", msg_code(get_name validator), " using ", msg_code(regex.inspect), ". Use ", msg_code("\\A"), " and ", msg_code("\\z"), " as anchors"),
93
93
  :line => value.line,
94
94
  :confidence => :high,
95
- :cwe_id => [777]
95
+ :cwe_id => [777],
96
+ :code => validator
96
97
  end
97
98
  end
98
99
 
@@ -63,9 +63,9 @@ module Brakeman::Options
63
63
  options[:exit_on_error] = exit_on_error
64
64
  end
65
65
 
66
- opts.on "--ensure-latest [DAYS]", Integer, "Fail when Brakeman is outdated. Optionally set minimum age in days." do |days|
66
+ opts.on "--ensure-latest [DAYS]", Integer, "Fail when Brakeman is outdated. Optionally set minimum age in days (1-15)." do |days|
67
67
  if days and not (1..15).include? days
68
- raise OptionParser::InvalidArgument
68
+ raise OptionParser::InvalidArgument, "Minimum age must be 1-15 days."
69
69
  end
70
70
 
71
71
  options[:ensure_latest] = days || true
@@ -56,8 +56,15 @@ module Brakeman
56
56
  else
57
57
  ERB.new(text, nil, '-').src
58
58
  end
59
- src.sub!(/^#.*\n/, '')
60
- src
59
+
60
+ # Encoding comment at the beginning throws off line numbers
61
+ # but the string is frozen in ERB 6.0.2+, so we don't want to
62
+ # unnecessarily duplicate the string
63
+ if src.start_with? '#'
64
+ src.sub(/^#.*\n/, '')
65
+ else
66
+ src
67
+ end
61
68
  end
62
69
  end
63
70
 
@@ -171,7 +171,7 @@ class Brakeman::HamlTemplateProcessor < Brakeman::TemplateProcessor
171
171
 
172
172
  def escaped_builder_method? exp
173
173
  case exp.method
174
- when :build, :build_aria, :build_boolean, :build_data, :build_id, :escape_html
174
+ when :build, :build_aria, :build_boolean, :build_class, :build_data, :build_id, :escape_html
175
175
  true? exp.first_arg
176
176
  else
177
177
  false
@@ -91,12 +91,25 @@ class Brakeman::ModelProcessor < Brakeman::BaseProcessor
91
91
  end
92
92
 
93
93
  def add_enum_method call
94
- arg = call.first_arg
95
- return unless hash? arg
96
- return unless symbol? arg[1]
94
+ if call.second_arg.nil?
95
+ # Rails < 7.1 syntax: enum status: { active: 0, archived: 1 }
96
+ arg = call.first_arg
97
+ return unless hash? arg
98
+ return unless symbol? arg[1]
99
+
100
+ enum_name = arg[1].value # first key
101
+ enums = arg[2] # first value
102
+ else
103
+ # Rails >= 7.1 syntax: enum :status, { active: 0, archived: 1 }
104
+ first_arg = call.first_arg
105
+ second_arg = call.second_arg
106
+ return unless symbol? first_arg
107
+ return unless hash? second_arg or array? second_arg
108
+
109
+ enum_name = first_arg.value
110
+ enums = second_arg
111
+ end
97
112
 
98
- enum_name = arg[1].value # first key
99
- enums = arg[2] # first value
100
113
  enums_name = pluralize(enum_name.to_s).to_sym
101
114
 
102
115
  call_line = call.line
@@ -1,38 +1,72 @@
1
1
  class Brakeman::Report::Sonar < Brakeman::Report::Base
2
2
  def generate_report
3
+ warnings = all_warnings
3
4
  report_object = {
4
- issues: all_warnings.map { |warning| issue_json(warning) }
5
+ rules: rules_json(warnings),
6
+ issues: warnings.map { |warning| issue_json(warning) }
5
7
  }
6
- return JSON.pretty_generate report_object
8
+ JSON.pretty_generate report_object
7
9
  end
8
-
10
+
9
11
  private
10
-
12
+
13
+ def rules_json(warnings)
14
+ warnings
15
+ .each_with_object({}) do |w, unique_warnings|
16
+ unique_warnings[[w.warning_code, w.confidence]] ||= w
17
+ end
18
+ .values
19
+ .map do |w|
20
+ {
21
+ id: rule_id(w),
22
+ name: w.warning_type.to_s,
23
+ description: w.link,
24
+ engineId: "Brakeman",
25
+ cleanCodeAttribute: "TRUSTWORTHY",
26
+ type: "VULNERABILITY",
27
+ severity: rule_severity_for(w.confidence),
28
+ impacts: [
29
+ {
30
+ softwareQuality: "SECURITY",
31
+ severity: impact_severity_for(w.confidence)
32
+ }
33
+ ]
34
+ }
35
+ end
36
+ end
37
+
11
38
  def issue_json(warning)
12
39
  {
13
- engineId: "Brakeman",
14
- ruleId: warning.warning_code,
15
- type: "VULNERABILITY",
16
- severity: severity_level_for(warning.confidence),
40
+ ruleId: rule_id(warning),
41
+ effortMinutes: (4 - warning.confidence) * 15,
17
42
  primaryLocation: {
18
43
  message: warning.message,
19
44
  filePath: warning.file.relative,
20
45
  textRange: {
21
- "startLine": warning.line || 1,
22
- "endLine": warning.line || 1,
46
+ startLine: warning.line || 1,
47
+ endLine: warning.line || 1
23
48
  }
24
- },
25
- effortMinutes: (4 - warning.confidence) * 15
49
+ }
26
50
  }
27
51
  end
28
52
 
29
- def severity_level_for(confidence)
30
- if confidence == 0
31
- "CRITICAL"
32
- elsif confidence == 1
33
- "MAJOR"
34
- else
35
- "MINOR"
53
+ def rule_id(warning)
54
+ "BRAKEMAN_#{warning.warning_code}_#{rule_severity_for(warning.confidence)}"
55
+ end
56
+
57
+ def rule_severity_for(confidence)
58
+ case confidence
59
+ when 0 then "CRITICAL"
60
+ when 1 then "MAJOR"
61
+ else "MINOR"
62
+ end
63
+ end
64
+
65
+ def impact_severity_for(confidence)
66
+ case confidence
67
+ when 0 then "HIGH"
68
+ when 1 then "MEDIUM"
69
+ else "LOW"
36
70
  end
37
71
  end
38
72
  end
@@ -1,3 +1,3 @@
1
1
  module Brakeman
2
- Version = "8.0.6"
2
+ Version = "8.1.0"
3
3
  end
@@ -175,7 +175,7 @@ class Brakeman::Warning
175
175
  def format_with_user_input strip = true, &block
176
176
  if self.user_input
177
177
  formatted = Brakeman::OutputProcessor.new.format(code, self.user_input, &block)
178
- formatted.gsub!(/(\t|\r|\n)+/, " ") if strip
178
+ formatted = formatted.gsub(/(\t|\r|\n)+/, " ") if strip
179
179
  formatted
180
180
  else
181
181
  format_code
@@ -321,4 +321,3 @@ class Brakeman::Warning
321
321
  formatted
322
322
  end
323
323
  end
324
-
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brakeman-min
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.0.6
4
+ version: 8.1.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: 2026-08-12 00:00:00.000000000 Z
11
+ date: 2026-09-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -365,7 +365,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
365
365
  - !ruby/object:Gem::Version
366
366
  version: '0'
367
367
  requirements: []
368
- rubygems_version: 3.4.19
368
+ rubygems_version: 3.5.11
369
369
  signing_key:
370
370
  specification_version: 4
371
371
  summary: Security vulnerability scanner for Ruby on Rails.