brakeman-min 6.0.1 → 6.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 32281be786de7f15331b0a18d3a95ee580824c71ebcaa5793dce46bf9e00eaf5
4
- data.tar.gz: 0b86124af3e493a0e30298e59339026f0bee8decd2a3851894b556fcb2e018a3
3
+ metadata.gz: 9bda2b7f2e2e83fd353b042c9c11857eb8d7bae3a3d2f3eb6facc97f58f3df06
4
+ data.tar.gz: ae4fd6a45a603d654ac5a8477810b5a79ee4041ed73e6f3bb59aea75bdf890a5
5
5
  SHA512:
6
- metadata.gz: 963ea6f98407ab7b887ac6e00a8ab7e6e9388357c7f96bd694e88e80a35e1be337f241fb0bb9708eed5a4f9d418b29c28b37e96fc6a57c9d59b6e032f855ea8a
7
- data.tar.gz: 295ba8cd987f5d26fff77fd204f50b54e64126bd5e700ff8d82789b32bbc58c3d4b4b8e8bc0b58841430d67290d0eb452fa302a428c109d9619b6f4b81d4a289
6
+ metadata.gz: 933fa4eebb2014b09c59e9bc946db21717cd9ba0b30eeeb3423fff4b8288f686161a5e33fa9e4c97f538e7aaaddc960e9826af77bc8f87dbe2dcfb846b915f7d
7
+ data.tar.gz: 131ddf8b1c80d4d113f8255dd2d10101d3e11c904f8ac364dfdca00d63ebd38c477abd7a0f606f3de293a55e4aaf27b61affdd8c1de86d0c26d6653d3a1904ec
data/CHANGES.md CHANGED
@@ -1,3 +1,16 @@
1
+ # 6.1.1 - 2023-12-24
2
+
3
+ * Handle racc as a default gem in Ruby 3.3.0
4
+
5
+ # 6.1.0 - 2023-12-04
6
+
7
+ * Add `--timing` to add timing duration for scan steps
8
+ * Fix keyword splats in filter arguments
9
+ * Add check for unfiltered search with Ransack
10
+ * Fix class method lookup in parent classes
11
+ * Handle `class << self`
12
+ * Add `PG::Connection.escape_string` as a SQL sanitization method (Joévin Soulenq)
13
+
1
14
  # 6.0.1 - 2023-07-20
2
15
 
3
16
  * Accept strings for `load_defaults` version
@@ -0,0 +1,53 @@
1
+ require 'brakeman/checks/base_check'
2
+
3
+ class Brakeman::CheckRansack < Brakeman::BaseCheck
4
+ Brakeman::Checks.add self
5
+
6
+ @description = "Checks for dangerous use of the Ransack library"
7
+
8
+ def run_check
9
+ return unless version_between? "0.0.0", "3.99", tracker.config.gem_version(:ransack)
10
+ check_ransack_calls
11
+ end
12
+
13
+ def check_ransack_calls
14
+ tracker.find_call(method: :ransack, nested: true).each do |result|
15
+ next unless original? result
16
+
17
+ call = result[:call]
18
+ arg = call.first_arg
19
+
20
+ # If an allow list is defined anywhere in the
21
+ # class or super classes, consider it safe
22
+ class_name = result[:chain].first
23
+
24
+ next if ransackable_allow_list?(class_name)
25
+
26
+ if input = has_immediate_user_input?(arg)
27
+ confidence = if tracker.find_class(class_name).nil?
28
+ confidence = :low
29
+ elsif result[:location][:file].relative.include? 'admin'
30
+ confidence = :medium
31
+ else
32
+ confidence = :high
33
+ end
34
+
35
+ message = msg('Unrestricted search using ', msg_code('ransack'), ' library called with ', msg_input(input), '. Limit search by defining ', msg_code('ransackable_attributes'), ' and ', msg_code('ransackable_associations'), ' methods in class or upgrade Ransack to version 4.0.0 or newer')
36
+
37
+ warn result: result,
38
+ warning_type: 'Missing Authorization',
39
+ warning_code: :ransack_search,
40
+ message: message,
41
+ user_input: input,
42
+ confidence: confidence,
43
+ cwe_id: [862],
44
+ link: 'https://positive.security/blog/ransack-data-exfiltration'
45
+ end
46
+ end
47
+ end
48
+
49
+ def ransackable_allow_list? class_name
50
+ tracker.find_method(:ransackable_attributes, class_name, :class) and
51
+ tracker.find_method(:ransackable_associations, class_name, :class)
52
+ end
53
+ end
@@ -591,7 +591,7 @@ class Brakeman::CheckSQL < Brakeman::BaseCheck
591
591
  :sanitize_sql_for_assignment, :sanitize_sql_for_conditions, :sanitize_sql_hash,
592
592
  :sanitize_sql_hash_for_assignment, :sanitize_sql_hash_for_conditions,
593
593
  :to_sql, :sanitize, :primary_key, :table_name_prefix, :table_name_suffix,
594
- :where_values_hash, :foreign_key, :uuid
594
+ :where_values_hash, :foreign_key, :uuid, :escape, :escape_string
595
595
  ]
596
596
 
597
597
  def ignore_methods_in_sql
@@ -244,6 +244,10 @@ module Brakeman::Options
244
244
  options[:debug] = true
245
245
  end
246
246
 
247
+ opts.on "--timing", "Measure time for scan steps" do
248
+ options[:show_timing] = true
249
+ end
250
+
247
251
  opts.on "-f",
248
252
  "--format TYPE",
249
253
  [:pdf, :text, :html, :csv, :tabs, :json, :markdown, :codeclimate, :cc, :plain, :table, :junit, :sarif, :sonar, :github],
@@ -529,8 +529,7 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
529
529
 
530
530
  #Process a method definition on self.
531
531
  def process_defs exp
532
- env.scope do
533
- set_env_defaults
532
+ meth_env do
534
533
  exp.body = process_all! exp.body
535
534
  end
536
535
  exp
@@ -84,6 +84,9 @@ module Brakeman::ModuleHelper
84
84
  res.line(exp.line)
85
85
  @current_method = nil
86
86
 
87
+ # TODO: if target is not self/nil, then
88
+ # the method should be added to `target`, not current class
89
+
87
90
  if @current_class
88
91
  @current_class.add_method @visibility, name, res, @current_file
89
92
  elsif @current_module
@@ -96,7 +99,13 @@ module Brakeman::ModuleHelper
96
99
  name = exp.method_name
97
100
 
98
101
  @current_method = name
99
- res = Sexp.new :defn, name, exp.formal_args, *process_all!(exp.body)
102
+
103
+ if @inside_sclass
104
+ res = Sexp.new :defs, s(:self), name, exp.formal_args, *process_all!(exp.body)
105
+ else
106
+ res = Sexp.new :defn, name, exp.formal_args, *process_all!(exp.body)
107
+ end
108
+
100
109
  res.line(exp.line)
101
110
  @current_method = nil
102
111
 
@@ -108,4 +117,25 @@ module Brakeman::ModuleHelper
108
117
 
109
118
  res
110
119
  end
120
+
121
+ # class << self
122
+ def process_sclass exp
123
+ @inside_sclass = true
124
+
125
+ process_all! exp
126
+
127
+ exp
128
+ ensure
129
+ @inside_sclass = false
130
+ end
131
+
132
+ def make_defs exp
133
+ # 'What if' there was some crazy code that had a
134
+ # defs inside a def inside an sclass? :|
135
+ return exp if node_type? exp, :defs
136
+
137
+ raise "Unexpected node type: #{exp.node_type}" unless node_type? exp, :defn
138
+
139
+ Sexp.new(:defs, s(:self), exp.method_name, exp.formal_args, *exp.body).line(exp.line)
140
+ end
111
141
  end
@@ -30,6 +30,12 @@ class Brakeman::LibraryProcessor < Brakeman::BaseProcessor
30
30
  end
31
31
 
32
32
  def process_defn exp
33
+ # TODO: Why is this different from ModuleHelper?
34
+
35
+ if @inside_sclass
36
+ exp = make_defs(exp)
37
+ end
38
+
33
39
  if exp.method_name == :initialize
34
40
  @alias_processor.process_safely exp.body_list
35
41
  @initializer_env = @alias_processor.only_ivars
@@ -30,6 +30,7 @@ class Brakeman::Scanner
30
30
  end
31
31
 
32
32
  @processor = processor || Brakeman::Processor.new(@app_tree, options)
33
+ @show_timing = tracker.options[:debug] || tracker.options[:show_timing]
33
34
  end
34
35
 
35
36
  #Returns the Tracker generated from the scan
@@ -37,35 +38,89 @@ class Brakeman::Scanner
37
38
  @processor.tracked_events
38
39
  end
39
40
 
41
+ def process_step description
42
+ Brakeman.notify "#{description}...".ljust(40)
43
+
44
+ if @show_timing
45
+ start_t = Time.now
46
+ yield
47
+ duration = Time.now - start_t
48
+
49
+ Brakeman.notify "(#{description}) Duration: #{duration} seconds"
50
+ else
51
+ yield
52
+ end
53
+ end
54
+
55
+ def process_step_file description
56
+ if @show_timing
57
+ Brakeman.notify "Processing #{description}"
58
+
59
+ start_t = Time.now
60
+ yield
61
+ duration = Time.now - start_t
62
+
63
+ Brakeman.notify "(#{description}) Duration: #{duration} seconds"
64
+ else
65
+ yield
66
+ end
67
+ end
68
+
40
69
  #Process everything in the Rails application
41
70
  def process
42
- Brakeman.notify "Processing gems... "
43
- process_gems
44
- guess_rails_version
45
- Brakeman.notify "Processing configuration... "
46
- process_config
47
- Brakeman.notify "Parsing files... "
48
- parse_files
49
- Brakeman.notify "Detecting file types... "
50
- detect_file_types
51
- Brakeman.notify "Processing initializers... "
52
- process_initializers
53
- Brakeman.notify "Processing libs... "
54
- process_libs
55
- Brakeman.notify "Processing routes... "
56
- process_routes
57
- Brakeman.notify "Processing templates... "
58
- process_templates
59
- Brakeman.notify "Processing data flow in templates... "
60
- process_template_data_flows
61
- Brakeman.notify "Processing models... "
62
- process_models
63
- Brakeman.notify "Processing controllers... "
64
- process_controllers
65
- Brakeman.notify "Processing data flow in controllers..."
66
- process_controller_data_flows
67
- Brakeman.notify "Indexing call sites... "
68
- index_call_sites
71
+ process_step 'Processing gems' do
72
+ process_gems
73
+ end
74
+
75
+ process_step 'Processing configuration' do
76
+ guess_rails_version
77
+ process_config
78
+ end
79
+
80
+ process_step 'Parsing files' do
81
+ parse_files
82
+ end
83
+
84
+ process_step 'Detecting file types' do
85
+ detect_file_types
86
+ end
87
+
88
+ process_step 'Processing initializers' do
89
+ process_initializers
90
+ end
91
+
92
+ process_step 'Processing libs' do
93
+ process_libs
94
+ end
95
+
96
+ process_step 'Processing routes' do
97
+ process_routes
98
+ end
99
+
100
+ process_step 'Processing templates' do
101
+ process_templates
102
+ end
103
+
104
+ process_step 'Processing data flow in templates' do
105
+ process_template_data_flows
106
+ end
107
+
108
+ process_step 'Processing models' do
109
+ process_models
110
+ end
111
+
112
+ process_step 'Processing controllers' do
113
+ process_controllers
114
+ end
115
+
116
+ process_step 'Processing data flow in controllers' do
117
+ process_controller_data_flows
118
+ end
119
+
120
+ process_step 'Indexing call sites' do
121
+ index_call_sites
122
+ end
123
+
69
124
  tracker
70
125
  end
71
126
 
@@ -214,8 +269,9 @@ class Brakeman::Scanner
214
269
  #Adds parsed information to tracker.initializers
215
270
  def process_initializers
216
271
  track_progress @file_list[:initializers] do |init|
217
- Brakeman.debug "Processing #{init[:path]}"
218
- process_initializer init
272
+ process_step_file init[:path] do
273
+ process_initializer init
274
+ end
219
275
  end
220
276
  end
221
277
 
@@ -234,8 +290,9 @@ class Brakeman::Scanner
234
290
  end
235
291
 
236
292
  track_progress @file_list[:libs] do |lib|
237
- Brakeman.debug "Processing #{lib.path}"
238
- process_lib lib
293
+ process_step_file lib.path do
294
+ process_lib lib
295
+ end
239
296
  end
240
297
  end
241
298
 
@@ -266,8 +323,9 @@ class Brakeman::Scanner
266
323
  #Adds processed controllers to tracker.controllers
267
324
  def process_controllers
268
325
  track_progress @file_list[:controllers] do |controller|
269
- Brakeman.debug "Processing #{controller.path}"
270
- process_controller controller
326
+ process_step_file controller.path do
327
+ process_controller controller
328
+ end
271
329
  end
272
330
  end
273
331
 
@@ -275,9 +333,10 @@ class Brakeman::Scanner
275
333
  controllers = tracker.controllers.sort_by { |name, _| name.to_s }
276
334
 
277
335
  track_progress controllers, "controllers" do |name, controller|
278
- Brakeman.debug "Processing #{name}"
279
- controller.src.each do |file, src|
280
- @processor.process_controller_alias name, src, nil, file
336
+ process_step_file name do
337
+ controller.src.each do |file, src|
338
+ @processor.process_controller_alias name, src, nil, file
339
+ end
281
340
  end
282
341
  end
283
342
 
@@ -300,8 +359,9 @@ class Brakeman::Scanner
300
359
  templates = @file_list[:templates].sort_by { |t| t[:path] }
301
360
 
302
361
  track_progress templates, "templates" do |template|
303
- Brakeman.debug "Processing #{template[:path]}"
304
- process_template template
362
+ process_step_file template[:path] do
363
+ process_template template
364
+ end
305
365
  end
306
366
  end
307
367
 
@@ -313,8 +373,9 @@ class Brakeman::Scanner
313
373
  templates = tracker.templates.sort_by { |name, _| name.to_s }
314
374
 
315
375
  track_progress templates, "templates" do |name, template|
316
- Brakeman.debug "Processing #{name}"
317
- @processor.process_template_alias template
376
+ process_step_file name do
377
+ @processor.process_template_alias template
378
+ end
318
379
  end
319
380
  end
320
381
 
@@ -323,8 +384,9 @@ class Brakeman::Scanner
323
384
  #Adds the processed models to tracker.models
324
385
  def process_models
325
386
  track_progress @file_list[:models] do |model|
326
- Brakeman.debug "Processing #{model[:path]}"
327
- process_model model[:path], model[:ast]
387
+ process_step_file model[:path] do
388
+ process_model model[:path], model[:ast]
389
+ end
328
390
  end
329
391
  end
330
392
 
@@ -120,16 +120,20 @@ module Brakeman
120
120
  filter[:methods] << a[1] if a.node_type == :lit
121
121
  end
122
122
 
123
- if args[-1].node_type == :hash
124
- option = args[-1][1][1]
125
- value = args[-1][2]
126
- case value.node_type
127
- when :array
128
- filter[option] = value.sexp_body.map {|v| v[1] }
129
- when :lit, :str
130
- filter[option] = value[1]
131
- else
132
- Brakeman.debug "[Notice] Unknown before_filter value: #{option} => #{value}"
123
+ options = args.last
124
+
125
+ if hash? options
126
+ # Probably only one option,
127
+ # but this also avoids issues with kwsplats
128
+ hash_iterate(options) do |option, value|
129
+ case value.node_type
130
+ when :array
131
+ filter[option.value] = value.sexp_body.map {|v| v[1] }
132
+ when :lit, :str
133
+ filter[option.value] = value[1]
134
+ else
135
+ Brakeman.debug "[Notice] Unknown before_filter value: #{option} => #{value}"
136
+ end
133
137
  end
134
138
  else
135
139
  filter[:all] = true
@@ -245,7 +245,7 @@ class Brakeman::Tracker
245
245
  end
246
246
 
247
247
  # Not in any included modules, check the parent
248
- @method_cache[cache_key] = find_method(method_name, klass.parent)
248
+ @method_cache[cache_key] = find_method(method_name, klass.parent, method_type)
249
249
  end
250
250
  end
251
251
 
@@ -1,3 +1,3 @@
1
1
  module Brakeman
2
- Version = "6.0.1"
2
+ Version = "6.1.1"
3
3
  end
@@ -130,6 +130,7 @@ module Brakeman::WarningCodes
130
130
  :insecure_rsa_padding_mode => 126,
131
131
  :missing_rsa_padding_mode => 127,
132
132
  :small_rsa_key_size => 128,
133
+ :ransack_search => 129,
133
134
 
134
135
  :custom_check => 9090,
135
136
  }
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: 6.0.1
4
+ version: 6.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Collins
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-07-20 00:00:00.000000000 Z
11
+ date: 2023-12-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -86,14 +86,14 @@ dependencies:
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '3.19'
89
+ version: 3.20.2
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '3.19'
96
+ version: 3.20.2
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: sexp_processor
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -136,6 +136,20 @@ dependencies:
136
136
  - - ">="
137
137
  - !ruby/object:Gem::Version
138
138
  version: '1.0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: racc
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :runtime
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
139
153
  description: Brakeman detects security vulnerabilities in Ruby on Rails applications
140
154
  via static analysis. This version of the gem only requires the minimum number of
141
155
  dependencies. Use the 'brakeman' gem for a full install.
@@ -198,6 +212,7 @@ files:
198
212
  - lib/brakeman/checks/check_pathname.rb
199
213
  - lib/brakeman/checks/check_permit_attributes.rb
200
214
  - lib/brakeman/checks/check_quote_table_name.rb
215
+ - lib/brakeman/checks/check_ransack.rb
201
216
  - lib/brakeman/checks/check_redirect.rb
202
217
  - lib/brakeman/checks/check_regex_dos.rb
203
218
  - lib/brakeman/checks/check_render.rb
@@ -361,7 +376,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
361
376
  - !ruby/object:Gem::Version
362
377
  version: '0'
363
378
  requirements: []
364
- rubygems_version: 3.3.3
379
+ rubygems_version: 3.2.3
365
380
  signing_key:
366
381
  specification_version: 4
367
382
  summary: Security vulnerability scanner for Ruby on Rails.