brakeman-min 7.1.2 → 8.0.1

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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +15 -0
  3. data/README.md +1 -1
  4. data/lib/brakeman/app_tree.rb +7 -2
  5. data/lib/brakeman/checks/check_model_attributes.rb +1 -1
  6. data/lib/brakeman/checks/check_render.rb +1 -27
  7. data/lib/brakeman/checks/check_render_rce.rb +43 -0
  8. data/lib/brakeman/checks/check_session_settings.rb +1 -1
  9. data/lib/brakeman/checks.rb +31 -25
  10. data/lib/brakeman/commandline.rb +8 -1
  11. data/lib/brakeman/file_parser.rb +3 -2
  12. data/lib/brakeman/logger.rb +264 -0
  13. data/lib/brakeman/options.rb +0 -9
  14. data/lib/brakeman/parsers/rails_erubi.rb +82 -0
  15. data/lib/brakeman/parsers/template_parser.rb +7 -15
  16. data/lib/brakeman/processor.rb +2 -2
  17. data/lib/brakeman/processors/controller_alias_processor.rb +1 -1
  18. data/lib/brakeman/processors/controller_processor.rb +3 -3
  19. data/lib/brakeman/processors/{erubis_template_processor.rb → erubi_template_procesor.rb} +3 -3
  20. data/lib/brakeman/processors/lib/rails2_config_processor.rb +4 -3
  21. data/lib/brakeman/processors/lib/rails2_route_processor.rb +1 -1
  22. data/lib/brakeman/processors/lib/render_helper.rb +1 -1
  23. data/lib/brakeman/processors/lib/render_path.rb +1 -1
  24. data/lib/brakeman/processors/model_processor.rb +1 -1
  25. data/lib/brakeman/report/ignore/config.rb +1 -1
  26. data/lib/brakeman/scanner.rb +25 -49
  27. data/lib/brakeman/tracker/collection.rb +12 -2
  28. data/lib/brakeman/tracker/config.rb +17 -13
  29. data/lib/brakeman/tracker/constants.rb +17 -2
  30. data/lib/brakeman/tracker/controller.rb +1 -1
  31. data/lib/brakeman/tracker.rb +7 -15
  32. data/lib/brakeman/version.rb +1 -1
  33. data/lib/brakeman.rb +89 -49
  34. metadata +6 -7
  35. data/lib/brakeman/parsers/erubis_patch.rb +0 -11
  36. data/lib/brakeman/parsers/rails2_erubis.rb +0 -9
  37. data/lib/brakeman/parsers/rails2_xss_plugin_erubis.rb +0 -52
  38. data/lib/brakeman/parsers/rails3_erubis.rb +0 -85
data/lib/brakeman.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'set'
2
+ require 'brakeman/logger'
2
3
  require 'brakeman/version'
3
4
 
4
5
  module Brakeman
@@ -32,6 +33,7 @@ module Brakeman
32
33
  @quiet = false
33
34
  @loaded_dependencies = []
34
35
  @vendored_paths = false
36
+ @logger = nil
35
37
 
36
38
  #Run Brakeman scan. Returns Tracker object.
37
39
  #
@@ -52,7 +54,6 @@ module Brakeman
52
54
  # * :highlight_user_input - highlight user input in reported warnings (default: true)
53
55
  # * :html_style - path to CSS file
54
56
  # * :ignore_model_output - consider models safe (default: false)
55
- # * :index_libs - add libraries to call index (default: true)
56
57
  # * :interprocedural - limited interprocedural processing of method calls (default: false)
57
58
  # * :message_limit - limit length of messages
58
59
  # * :min_confidence - minimum confidence (0-2, 0 is highest)
@@ -71,7 +72,6 @@ module Brakeman
71
72
  # * :safe_methods - array of methods to consider safe
72
73
  # * :show_ignored - Display warnings that are usually ignored
73
74
  # * :sql_safe_methods - array of sql sanitization methods to consider safe
74
- # * :skip_libs - do not process lib/ directory (default: false)
75
75
  # * :skip_vendor - do not process vendor/ directory (default: true)
76
76
  # * :skip_checks - checks not to run (run all if not specified)
77
77
  # * :absolute_paths - show absolute path of each file (default: false)
@@ -79,6 +79,10 @@ module Brakeman
79
79
  #
80
80
  #Alternatively, just supply a path as a string.
81
81
  def self.run options
82
+ if not $stderr.tty? and options[:report_progress].nil?
83
+ options[:report_progress] = false
84
+ end
85
+
82
86
  options = set_options options
83
87
 
84
88
  @quiet = !!options[:quiet]
@@ -88,18 +92,37 @@ module Brakeman
88
92
  options[:report_progress] = false
89
93
  end
90
94
 
95
+ @logger = options[:logger] || set_default_logger(options)
96
+
91
97
  if options[:use_prism]
92
98
  begin
93
99
  require 'prism'
94
- notify '[Notice] Using Prism parser'
95
100
  rescue LoadError => e
96
- Brakeman.debug "[Notice] Asked to use Prism, but failed to load: #{e}"
101
+ Brakeman.alert "Asked to use Prism, but failed to load: #{e}"
97
102
  end
98
103
  end
99
104
 
105
+ Brakeman.announce "Brakeman v#{Brakeman::Version}"
106
+
100
107
  scan options
101
108
  end
102
109
 
110
+ def self.logger
111
+ @logger
112
+ end
113
+
114
+ def self.logger= log
115
+ @logger = log
116
+ end
117
+
118
+ def self.set_default_logger(options = {})
119
+ @logger = Brakeman::Logger.get_logger(options)
120
+ end
121
+
122
+ def self.cleanup(newline = true)
123
+ @logger.cleanup(newline) if @logger
124
+ end
125
+
103
126
  #Sets up options for run, checks given application path
104
127
  def self.set_options options
105
128
  if options.is_a? String
@@ -152,6 +175,9 @@ module Brakeman
152
175
  require 'yaml'
153
176
  options = YAML.safe_load_file config, permitted_classes: [Symbol], symbolize_names: true
154
177
 
178
+ # Brakeman.logger is probably not set yet
179
+ logger = Brakeman::Logger.get_logger(options || line_options)
180
+
155
181
  if options
156
182
  options.each { |k, v| options[k] = Set.new v if v.is_a? Array }
157
183
 
@@ -162,15 +188,16 @@ module Brakeman
162
188
  if options.include? :additional_checks_path
163
189
  options.delete :additional_checks_path
164
190
 
165
- notify "[Notice] Ignoring additional check paths in config file. Use --allow-check-paths-in-config to allow" unless (options[:quiet] || quiet)
191
+ logger.alert 'Ignoring additional check paths in config file. Use --allow-check-paths-in-config to allow' unless (options[:quiet] || quiet)
166
192
  end
167
193
  end
168
194
 
169
195
  # notify if options[:quiet] and quiet is nil||false
170
- notify "[Notice] Using configuration in #{config}" unless (options[:quiet] || quiet)
196
+ # potentially remove these checks now that logger is used
197
+ logger.alert "Using configuration in #{config}" unless (options[:quiet] || quiet)
171
198
  options
172
199
  else
173
- notify "[Notice] Empty configuration file: #{config}" unless quiet
200
+ logger.alert "Empty configuration file: #{config}" unless quiet
174
201
  {}
175
202
  end
176
203
  else
@@ -209,7 +236,6 @@ module Brakeman
209
236
  :html_style => "#{File.expand_path(File.dirname(__FILE__))}/brakeman/format/style.css",
210
237
  :ignore_model_output => false,
211
238
  :ignore_redirect_to_model => true,
212
- :index_libs => true,
213
239
  :message_limit => 100,
214
240
  :min_confidence => 2,
215
241
  :output_color => true,
@@ -367,6 +393,12 @@ module Brakeman
367
393
 
368
394
  options.delete :create_config
369
395
 
396
+ if options[:logger]
397
+ @logger = options.delete(:logger)
398
+ else
399
+ set_default_logger(options)
400
+ end
401
+
370
402
  options.each do |k,v|
371
403
  if v.is_a? Set
372
404
  options[k] = v.to_a
@@ -377,9 +409,10 @@ module Brakeman
377
409
  File.open file, "w" do |f|
378
410
  YAML.dump options, f
379
411
  end
380
- notify "Output configuration to #{file}"
412
+
413
+ announce "Output configuration to #{file}"
381
414
  else
382
- notify YAML.dump(options)
415
+ $stdout.puts YAML.dump(options)
383
416
  end
384
417
  end
385
418
 
@@ -394,43 +427,39 @@ module Brakeman
394
427
  #Run a scan. Generally called from Brakeman.run instead of directly.
395
428
  def self.scan options
396
429
  #Load scanner
397
- notify "Loading scanner..."
430
+ scanner, tracker = nil
398
431
 
399
- begin
400
- require 'brakeman/scanner'
401
- rescue LoadError
402
- raise NoBrakemanError, "Cannot find lib/ directory."
403
- end
432
+ process_step 'Loading scanner' do
433
+ begin
434
+ require 'brakeman/scanner'
435
+ rescue LoadError
436
+ raise NoBrakemanError, 'Cannot find lib/ directory.'
437
+ end
404
438
 
405
- add_external_checks options
439
+ add_external_checks options
406
440
 
407
- #Start scanning
408
- scanner = Scanner.new options
409
- tracker = scanner.tracker
441
+ #Start scanning
442
+ scanner = Scanner.new options
443
+ tracker = scanner.tracker
410
444
 
411
- check_for_missing_checks options[:run_checks], options[:skip_checks], options[:enable_checks]
445
+ check_for_missing_checks options[:run_checks], options[:skip_checks], options[:enable_checks]
446
+ end
412
447
 
413
- notify "Processing application in #{tracker.app_path}"
448
+ logger.announce "Scanning #{tracker.app_path}"
414
449
  scanner.process
415
450
 
416
- if options[:parallel_checks]
417
- notify "Running checks in parallel..."
418
- else
419
- notify "Running checks..."
420
- end
421
-
422
451
  tracker.run_checks
423
452
 
424
453
  self.filter_warnings tracker, options
425
454
 
426
455
  if options[:output_files]
427
- notify "Generating report..."
428
-
429
- write_report_to_files tracker, options[:output_files]
456
+ process_step 'Generating report' do
457
+ write_report_to_files tracker, options[:output_files]
458
+ end
430
459
  elsif options[:print_report]
431
- notify "Generating report..."
432
-
433
- write_report_to_formats tracker, options[:output_formats]
460
+ process_step 'Generating report' do
461
+ write_report_to_formats tracker, options[:output_formats]
462
+ end
434
463
  end
435
464
 
436
465
  tracker
@@ -449,7 +478,8 @@ module Brakeman
449
478
  File.open output_file, "w" do |f|
450
479
  f.write tracker.report.format(tracker.options[:output_formats][idx])
451
480
  end
452
- notify "Report saved in '#{output_file}'"
481
+
482
+ logger.announce "Report saved in '#{output_file}'"
453
483
  end
454
484
  end
455
485
  private_class_method :write_report_to_files
@@ -493,12 +523,16 @@ module Brakeman
493
523
  Rescanner.new(options, tracker.processor, files).recheck
494
524
  end
495
525
 
496
- def self.notify message
497
- $stderr.puts message unless @quiet
526
+ def self.announce message
527
+ logger.announce message
528
+ end
529
+
530
+ def self.alert message
531
+ logger.alert message
498
532
  end
499
533
 
500
534
  def self.debug message
501
- $stderr.puts message if @debug
535
+ logger.debug message
502
536
  end
503
537
 
504
538
  # Compare JSON output from a previous scan and return the diff of the two scans
@@ -510,7 +544,7 @@ module Brakeman
510
544
  begin
511
545
  previous_results = JSON.parse(File.read(options[:previous_results_json]), :symbolize_names => true)[:warnings]
512
546
  rescue JSON::ParserError
513
- self.notify "Error parsing comparison file: #{options[:previous_results_json]}"
547
+ self.alert "Error parsing comparison file: #{options[:previous_results_json]}"
514
548
  exit!
515
549
  end
516
550
 
@@ -565,6 +599,7 @@ module Brakeman
565
599
 
566
600
  def self.filter_warnings tracker, options
567
601
  require 'brakeman/report/ignore/config'
602
+ config = nil
568
603
 
569
604
  app_tree = Brakeman::AppTree.from_options(options)
570
605
 
@@ -576,16 +611,17 @@ module Brakeman
576
611
  return
577
612
  end
578
613
 
579
- notify "Filtering warnings..."
580
-
581
- if options[:interactive_ignore]
582
- require 'brakeman/report/ignore/interactive'
583
- config = InteractiveIgnorer.new(file, tracker.warnings).start
584
- else
585
- notify "[Notice] Using '#{file}' to filter warnings"
586
- config = IgnoreConfig.new(file, tracker.warnings)
587
- config.read_from_file
588
- config.filter_ignored
614
+ process_step "Filtering warnings..." do
615
+ if options[:interactive_ignore]
616
+ require 'brakeman/report/ignore/interactive'
617
+ logger.cleanup
618
+ config = InteractiveIgnorer.new(file, tracker.warnings).start
619
+ else
620
+ logger.announce "Using '#{file}' to filter warnings"
621
+ config = IgnoreConfig.new(file, tracker.warnings)
622
+ config.read_from_file
623
+ config.filter_ignored
624
+ end
589
625
  end
590
626
 
591
627
  tracker.ignored_filter = config
@@ -615,6 +651,10 @@ module Brakeman
615
651
  @quiet = val
616
652
  end
617
653
 
654
+ def self.process_step(description, &)
655
+ logger.context(description, &)
656
+ end
657
+
618
658
  class DependencyError < RuntimeError; end
619
659
  class NoBrakemanError < RuntimeError; end
620
660
  class NoApplication < RuntimeError; end
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: 7.1.2
4
+ version: 8.0.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: 2025-12-25 00:00:00.000000000 Z
11
+ date: 2026-01-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -204,6 +204,7 @@ files:
204
204
  - lib/brakeman/checks/check_render.rb
205
205
  - lib/brakeman/checks/check_render_dos.rb
206
206
  - lib/brakeman/checks/check_render_inline.rb
207
+ - lib/brakeman/checks/check_render_rce.rb
207
208
  - lib/brakeman/checks/check_response_splitting.rb
208
209
  - lib/brakeman/checks/check_reverse_tabnabbing.rb
209
210
  - lib/brakeman/checks/check_route_dos.rb
@@ -246,14 +247,12 @@ files:
246
247
  - lib/brakeman/file_parser.rb
247
248
  - lib/brakeman/file_path.rb
248
249
  - lib/brakeman/format/style.css
250
+ - lib/brakeman/logger.rb
249
251
  - lib/brakeman/messages.rb
250
252
  - lib/brakeman/options.rb
251
- - lib/brakeman/parsers/erubis_patch.rb
252
253
  - lib/brakeman/parsers/haml6_embedded.rb
253
254
  - lib/brakeman/parsers/haml_embedded.rb
254
- - lib/brakeman/parsers/rails2_erubis.rb
255
- - lib/brakeman/parsers/rails2_xss_plugin_erubis.rb
256
- - lib/brakeman/parsers/rails3_erubis.rb
255
+ - lib/brakeman/parsers/rails_erubi.rb
257
256
  - lib/brakeman/parsers/slim_embedded.rb
258
257
  - lib/brakeman/parsers/template_parser.rb
259
258
  - lib/brakeman/processor.rb
@@ -263,7 +262,7 @@ files:
263
262
  - lib/brakeman/processors/controller_alias_processor.rb
264
263
  - lib/brakeman/processors/controller_processor.rb
265
264
  - lib/brakeman/processors/erb_template_processor.rb
266
- - lib/brakeman/processors/erubis_template_processor.rb
265
+ - lib/brakeman/processors/erubi_template_procesor.rb
267
266
  - lib/brakeman/processors/gem_processor.rb
268
267
  - lib/brakeman/processors/haml6_template_processor.rb
269
268
  - lib/brakeman/processors/haml_template_processor.rb
@@ -1,11 +0,0 @@
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,9 +0,0 @@
1
- Brakeman.load_brakeman_dependency 'erubis'
2
-
3
- require 'brakeman/parsers/erubis_patch'
4
-
5
- #Erubis processor which ignores any output which is plain text.
6
- class Brakeman::ScannerErubis < Erubis::Eruby
7
- include Erubis::NoTextEnhancer
8
- include Brakeman::ErubisPatch
9
- end
@@ -1,52 +0,0 @@
1
- Brakeman.load_brakeman_dependency 'erubis'
2
-
3
- require 'brakeman/parsers/erubis_patch'
4
-
5
- #This is from the rails_xss plugin for Rails 2
6
- class Brakeman::Rails2XSSPluginErubis < ::Erubis::Eruby
7
- include Brakeman::ErubisPatch
8
-
9
- def add_preamble(src)
10
- #src << "@output_buffer = ActiveSupport::SafeBuffer.new;"
11
- end
12
-
13
- #This is different from rails_xss - fixes some line number issues
14
- def add_text(src, text)
15
- if text == "\n"
16
- src << "\n"
17
- elsif text.include? "\n"
18
- lines = text.split("\n")
19
- if text.match(/\n\z/)
20
- lines.each do |line|
21
- src << "@output_buffer.safe_concat('" << escape_text(line) << "');\n"
22
- end
23
- else
24
- lines[0..-2].each do |line|
25
- src << "@output_buffer.safe_concat('" << escape_text(line) << "');\n"
26
- end
27
-
28
- src << "@output_buffer.safe_concat('" << escape_text(lines.last) << "');"
29
- end
30
- else
31
- src << "@output_buffer.safe_concat('" << escape_text(text) << "');"
32
- end
33
- end
34
-
35
- BLOCK_EXPR = /\s+(do|\{)(\s*\|[^|]*\|)?\s*\Z/
36
-
37
- def add_expr_literal(src, code)
38
- if code =~ BLOCK_EXPR
39
- src << "@output_buffer.safe_concat((" << $1 << ").to_s);"
40
- else
41
- src << '@output_buffer << ((' << code << ').to_s);'
42
- end
43
- end
44
-
45
- def add_expr_escaped(src, code)
46
- src << '@output_buffer << ' << escaped_expr(code) << ';'
47
- end
48
-
49
- def add_postamble(src)
50
- #src << '@output_buffer.to_s'
51
- end
52
- end
@@ -1,85 +0,0 @@
1
- Brakeman.load_brakeman_dependency 'erubis'
2
-
3
- require 'brakeman/parsers/erubis_patch'
4
-
5
- # This is from Rails 5 version of the Erubis handler
6
- # https://github.com/rails/rails/blob/ec608107801b1e505db03ba76bae4a326a5804ca/actionview/lib/action_view/template/handlers/erb.rb#L7-L73
7
- class Brakeman::Rails3Erubis < ::Erubis::Eruby
8
- include Brakeman::ErubisPatch
9
-
10
- def add_preamble(src)
11
- @newline_pending = 0
12
- src << "_this_is_to_make_yields_syntactally_correct {"
13
- src << "@output_buffer = output_buffer || ActionView::OutputBuffer.new;"
14
- end
15
-
16
- def add_text(src, text)
17
- return if text.empty?
18
-
19
- if text == "\n"
20
- @newline_pending += 1
21
- else
22
- src << "@output_buffer.safe_append='"
23
- src << "\n" * @newline_pending if @newline_pending > 0
24
- src << escape_text(text)
25
- src << "'.freeze;"
26
-
27
- @newline_pending = 0
28
- end
29
- end
30
-
31
- # Erubis toggles <%= and <%== behavior when escaping is enabled.
32
- # We override to always treat <%== as escaped.
33
- def add_expr(src, code, indicator)
34
- case indicator
35
- when '=='
36
- add_expr_escaped(src, code)
37
- else
38
- super
39
- end
40
- end
41
-
42
- BLOCK_EXPR = /\s*((\s+|\))do|\{)(\s*\|[^|]*\|)?\s*\Z/
43
-
44
- def add_expr_literal(src, code)
45
- flush_newline_if_pending(src)
46
- if code =~ BLOCK_EXPR
47
- src << '@output_buffer.append= ' << code
48
- else
49
- src << '@output_buffer.append=(' << code << ');'
50
- end
51
- end
52
-
53
- def add_expr_escaped(src, code)
54
- flush_newline_if_pending(src)
55
- if code =~ BLOCK_EXPR
56
- src << "@output_buffer.safe_expr_append= " << code
57
- else
58
- src << "@output_buffer.safe_expr_append=(" << code << ");"
59
- end
60
- end
61
-
62
- def add_stmt(src, code)
63
- flush_newline_if_pending(src)
64
- super
65
- end
66
-
67
- def add_postamble(src)
68
- flush_newline_if_pending(src)
69
- src << '@output_buffer.to_s; }'
70
- end
71
-
72
- def flush_newline_if_pending(src)
73
- if @newline_pending > 0
74
- src << "@output_buffer.safe_append='#{"\n" * @newline_pending}'.freeze;"
75
- @newline_pending = 0
76
- end
77
- end
78
-
79
- # This is borrowed from graphql's erb plugin:
80
- # https://github.com/github/graphql-client/blob/51e76bd8d8b2ac0021d8fef7468b9a294e4bd6e8/lib/graphql/client/erubis.rb#L33-L38
81
- def convert_input(src, input)
82
- input = input.gsub(/<%graphql/, "<%#")
83
- super(src, input)
84
- end
85
- end