package-audit 0.6.0 → 0.6.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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/lib/package/audit/npm/node_collection.rb +17 -0
  3. data/lib/package/audit/npm/npm_meta_data.rb +24 -2
  4. data/lib/package/audit/npm/vulnerability_finder.rb +7 -1
  5. data/lib/package/audit/ruby/bundler_specs.rb +15 -1
  6. data/lib/package/audit/services/command_parser.rb +28 -6
  7. data/lib/package/audit/services/config_cleaner.rb +221 -0
  8. data/lib/package/audit/util/spinner.rb +1 -1
  9. data/lib/package/audit/util/summary_printer.rb +7 -6
  10. data/lib/package/audit/version.rb +1 -1
  11. metadata +9 -53
  12. data/sig/package/audit/cli.rbs +0 -35
  13. data/sig/package/audit/const/cmd.rbs +0 -14
  14. data/sig/package/audit/const/fields.rbs +0 -11
  15. data/sig/package/audit/const/file.rbs +0 -14
  16. data/sig/package/audit/const/time.rbs +0 -11
  17. data/sig/package/audit/const/yaml.rbs +0 -13
  18. data/sig/package/audit/enum/format.rbs +0 -12
  19. data/sig/package/audit/enum/group.rbs +0 -15
  20. data/sig/package/audit/enum/option.rbs +0 -14
  21. data/sig/package/audit/enum/report.rbs +0 -12
  22. data/sig/package/audit/enum/risk_explanation.rbs +0 -12
  23. data/sig/package/audit/enum/risk_type.rbs +0 -12
  24. data/sig/package/audit/enum/technology.rbs +0 -12
  25. data/sig/package/audit/enum/vulnerability_type.rbs +0 -15
  26. data/sig/package/audit/formatter/base.rbs +0 -9
  27. data/sig/package/audit/formatter/risk_printer.rbs +0 -13
  28. data/sig/package/audit/formatter/version_date.rbs +0 -13
  29. data/sig/package/audit/formatter/version_printer.rbs +0 -14
  30. data/sig/package/audit/formatter/vulnerability.rbs +0 -13
  31. data/sig/package/audit/models/package.rbs +0 -47
  32. data/sig/package/audit/models/risk.rbs +0 -12
  33. data/sig/package/audit/npm/node_collection.rbs +0 -28
  34. data/sig/package/audit/npm/npm_meta_data.rbs +0 -19
  35. data/sig/package/audit/npm/vulnerability_finder.rbs +0 -21
  36. data/sig/package/audit/npm/yarn_lock_parser.rbs +0 -22
  37. data/sig/package/audit/ruby/bundler_specs.rbs +0 -11
  38. data/sig/package/audit/ruby/gem_collection.rbs +0 -22
  39. data/sig/package/audit/ruby/gem_meta_data.rbs +0 -23
  40. data/sig/package/audit/ruby/vulnerability_finder.rbs +0 -18
  41. data/sig/package/audit/services/command_parser.rbs +0 -37
  42. data/sig/package/audit/services/duplicate_package_merger.rbs +0 -11
  43. data/sig/package/audit/services/package_filter.rbs +0 -26
  44. data/sig/package/audit/services/package_finder.rbs +0 -26
  45. data/sig/package/audit/services/package_printer.rbs +0 -30
  46. data/sig/package/audit/services/risk_calculator.rbs +0 -21
  47. data/sig/package/audit/technology/detector.rbs +0 -19
  48. data/sig/package/audit/technology/validator.rbs +0 -19
  49. data/sig/package/audit/util/bash_color.rbs +0 -21
  50. data/sig/package/audit/util/risk_legend.rbs +0 -9
  51. data/sig/package/audit/util/spinner.rbs +0 -24
  52. data/sig/package/audit/util/summary_printer.rbs +0 -33
  53. data/sig/package/audit/version.rbs +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f9f4f23e752d513ff8a35a325296edf1d2d0a99b200d3e64ae92ce00ce145ac1
4
- data.tar.gz: 043a77af2e0a46688ba0964e6d595bfe3a50fecc59f73f4957c24ca0ad4c9cbe
3
+ metadata.gz: c4f817af73ba4616da54a934f0f6c4120d921e6026226c20a02c592c6b55e064
4
+ data.tar.gz: 818282a8f489ba8afd7b9675b78db96c3e2b9b18731415085ff44c25eaf07a77
5
5
  SHA512:
6
- metadata.gz: 3ebd17673929a378540502f8757397bd37c1a86121fa99f691fb94b537b53f9eec5f7698be6076af0cc0aa7c163458eede4875316e6755a1a05e4a7b8e33e83b
7
- data.tar.gz: 190255842a47fbf044d75703cf8263b177a91ed5a282c7d610cb99f27ad3fe194170b73ba09575afb6fc181b26f2d797fa11f4e9f481cb8f1619af581bd61f86
6
+ metadata.gz: 46267de0e991aaf0e1fdeb4f8c778cc2a59abf49f7d7a0849ae9731c9fb633ae8c958ac1865bf17aa98d50cd359e8e30d16975031f4dfd4fc1a7c2aacf6868fc
7
+ data.tar.gz: 65c6acb5e9e224f6736781f1db26eee0ec7772f220c87b8e8da1f2cecc872cfb667f78336314ad4b670000f849c60051087cdc9cda1b9e69ad11d896b717c471
@@ -58,9 +58,26 @@ module Package
58
58
  package_json = JSON.parse(File.read("#{@dir}/#{Const::File::PACKAGE_JSON}"), symbolize_names: true)
59
59
  default_deps = package_json[:dependencies] || {}
60
60
  dev_deps = package_json[:devDependencies] || {}
61
+
62
+ # Filter out local dependencies before processing
63
+ default_deps = filter_local_dependencies(default_deps)
64
+ dev_deps = filter_local_dependencies(dev_deps)
65
+
61
66
  [default_deps, dev_deps]
62
67
  end
63
68
 
69
+ def filter_local_dependencies(dependencies)
70
+ dependencies.reject { |_name, version| local_dependency?(version) }
71
+ end
72
+
73
+ def local_dependency?(version)
74
+ # Check for local file paths
75
+ version.to_s.start_with?('file:', 'link:', './', '../') ||
76
+ version.to_s.include?('file:') ||
77
+ # Check for git repositories with local paths
78
+ (version.to_s.start_with?('git+') && version.to_s.include?('file:'))
79
+ end
80
+
64
81
  def fetch_from_lock_file
65
82
  default_deps, dev_deps = fetch_from_package_json
66
83
  if File.exist?("#{@dir}/#{Const::File::YARN_LOCK}")
@@ -1,5 +1,6 @@
1
1
  require 'json'
2
2
  require 'net/http'
3
+ require 'socket'
3
4
 
4
5
  module Package
5
6
  module Audit
@@ -11,7 +12,7 @@ module Package
11
12
  @packages = packages
12
13
  end
13
14
 
14
- def fetch # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
15
+ def fetch # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
15
16
  threads = @packages.map do |package|
16
17
  Thread.new do
17
18
  response = Net::HTTP.get_response(URI.parse("#{REGISTRY_URL}/#{package.name}"))
@@ -20,14 +21,35 @@ module Package
20
21
 
21
22
  json_package = JSON.parse(response.body, symbolize_names: true)
22
23
  update_meta_data(package, json_package)
24
+ rescue Net::TimeoutError, Net::OpenTimeout, Net::ReadTimeout => e
25
+ warn "Warning: Network timeout while fetching metadata for #{package.name}: #{e.message}"
26
+ Thread.current[:exception] = e
27
+ rescue SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH => e
28
+ warn "Warning: Network error while fetching metadata for #{package.name}: #{e.message}"
29
+ Thread.current[:exception] = e
23
30
  rescue StandardError => e
24
31
  Thread.current[:exception] = e
25
32
  end
26
33
  end
34
+
35
+ network_errors = []
27
36
  threads.each do |thread|
28
37
  thread.join
29
- raise thread[:exception] if thread[:exception]
38
+ next unless thread[:exception]
39
+
40
+ case thread[:exception]
41
+ when Net::TimeoutError, Net::OpenTimeout, Net::ReadTimeout, SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH # rubocop:disable Layout/LineLength
42
+ network_errors << thread[:exception]
43
+ else
44
+ raise thread[:exception]
45
+ end
46
+ end
47
+
48
+ unless network_errors.empty?
49
+ warn "Warning: #{network_errors.size} network error(s) occurred while fetching package metadata."
50
+ warn 'Some packages may not show complete version information.'
30
51
  end
52
+
31
53
  @packages
32
54
  end
33
55
 
@@ -1,3 +1,5 @@
1
+ require 'open3'
2
+
1
3
  require_relative '../const/cmd'
2
4
  require_relative '../enum/vulnerability_type'
3
5
 
@@ -14,7 +16,11 @@ module Package
14
16
  end
15
17
 
16
18
  def run
17
- json_string_lines = `#{format(Const::Cmd::YARN_AUDIT_JSON, @dir)}`
19
+ # Suppress Node.js url.parse deprecation warnings from yarn audit command
20
+ command = format(Const::Cmd::YARN_AUDIT_JSON, @dir)
21
+ env_vars = { 'NODE_NO_WARNINGS' => '1' }
22
+
23
+ json_string_lines, = Open3.capture3(env_vars, command)
18
24
  array = json_string_lines.scan(AUDIT_ADVISORY_REGEX)
19
25
 
20
26
  vulnerability_json_array = JSON.parse("[#{array.join(',')}]", symbolize_names: true)
@@ -9,10 +9,11 @@ module Package
9
9
  module Ruby
10
10
  class BundlerSpecs
11
11
  def self.all(dir)
12
- Bundler.with_unbundled_env do
12
+ specs = Bundler.with_unbundled_env do
13
13
  ENV['BUNDLE_GEMFILE'] = "#{dir}/Gemfile"
14
14
  Bundler.ui.silence { Bundler.definition.resolve }
15
15
  end
16
+ filter_local_dependencies(specs)
16
17
  end
17
18
 
18
19
  def self.gemfile(dir)
@@ -30,6 +31,19 @@ module Package
30
31
  end
31
32
  gemfile_specs
32
33
  end
34
+
35
+ def self.filter_local_dependencies(specs)
36
+ specs.reject { |spec| local_dependency?(spec) }
37
+ end
38
+
39
+ def self.local_dependency?(spec)
40
+ # Check if the gem has a local source (path or git with local path)
41
+ source = spec.source
42
+ return true if source.is_a?(Bundler::Source::Path)
43
+ return true if source.is_a?(Bundler::Source::Git) && source.uri.start_with?('file:', './', '../')
44
+
45
+ false
46
+ end
33
47
  end
34
48
  end
35
49
  end
@@ -6,6 +6,7 @@ require_relative '../technology/detector'
6
6
  require_relative '../technology/validator'
7
7
  require_relative '../util/spinner'
8
8
  require_relative '../util/summary_printer'
9
+ require_relative 'config_cleaner'
9
10
  require_relative 'package_finder'
10
11
  require_relative 'package_printer'
11
12
 
@@ -13,7 +14,7 @@ require 'yaml'
13
14
 
14
15
  module Package
15
16
  module Audit
16
- class CommandParser
17
+ class CommandParser # rubocop:disable Metrics/ClassLength
17
18
  def initialize(dir, options, report)
18
19
  @dir = dir
19
20
  @options = options
@@ -22,7 +23,7 @@ module Package
22
23
  @groups = @options[Enum::Option::GROUP]
23
24
  @technologies = parse_technologies!
24
25
  validate_format!
25
- @spinner = Util::Spinner.new('Evaluating packages and their dependencies...')
26
+ @spinner = Util::Spinner.new("Evaluating packages and their dependencies for #{human_readable_technologies}...")
26
27
  end
27
28
 
28
29
  def run
@@ -42,6 +43,7 @@ module Package
42
43
  def process_technologies # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
43
44
  mutex = Mutex.new
44
45
  cumulative_pkgs = []
46
+ all_packages_for_config = []
45
47
  thread_index = 0
46
48
 
47
49
  @spinner.start
@@ -49,11 +51,14 @@ module Package
49
51
  Thread.new do
50
52
  all_pkgs, ignored_pkgs = PackageFinder.new(@config, @dir, @report, @groups).run(technology)
51
53
  ignored_pkgs = [] if @options[Enum::Option::INCLUDE_IGNORED]
52
- cumulative_pkgs += (all_pkgs || []) - (ignored_pkgs || [])
54
+ active_pkgs = (all_pkgs || []) - (ignored_pkgs || [])
55
+ cumulative_pkgs += active_pkgs
56
+ mutex.synchronize { all_packages_for_config += all_pkgs || [] }
57
+
53
58
  sleep 0.1 while technology_index != thread_index # print each technology in order
54
59
  mutex.synchronize do
55
60
  @spinner.stop
56
- print_results(technology, (all_pkgs || []) - (ignored_pkgs || []), ignored_pkgs || [])
61
+ print_results(technology, active_pkgs, ignored_pkgs || [])
57
62
  thread_index += 1
58
63
  @spinner.start
59
64
  end
@@ -65,6 +70,10 @@ module Package
65
70
  thread.join
66
71
  raise thread[:exception] if thread[:exception]
67
72
  end
73
+
74
+ @spinner.stop # Stop spinner before cleaning config to ensure clean output
75
+ clean_config(all_packages_for_config)
76
+
68
77
  cumulative_pkgs.any? ? 1 : 0
69
78
  ensure
70
79
  @spinner.stop
@@ -73,7 +82,7 @@ module Package
73
82
  def print_results(technology, pkgs, ignored_pkgs)
74
83
  PackagePrinter.new(@options, pkgs).print(Const::Fields::DEFAULT)
75
84
  print_summary(technology, pkgs, ignored_pkgs) unless @options[Enum::Option::FORMAT] == Enum::Format::CSV
76
- print_disclaimer(technology) unless @options[Enum::Option::FORMAT] == Enum::Format::CSV || pkgs.empty?
85
+ print_disclaimer(technology) unless @options[Enum::Option::FORMAT] || pkgs.empty?
77
86
  end
78
87
 
79
88
  def print_summary(technology, pkgs, ignored_pkgs)
@@ -123,7 +132,20 @@ module Package
123
132
  def parse_technologies!
124
133
  technology_validator = Technology::Validator.new(@dir)
125
134
  @options[Enum::Option::TECHNOLOGY]&.each { |technology| technology_validator.validate! technology }
126
- @options[Enum::Option::TECHNOLOGY] || Technology::Detector.new(@dir).detect
135
+ (@options[Enum::Option::TECHNOLOGY] || Technology::Detector.new(@dir).detect).sort
136
+ end
137
+
138
+ def clean_config(all_packages)
139
+ ConfigCleaner.new(@dir, @config, all_packages, @options).run
140
+ end
141
+
142
+ def human_readable_technologies
143
+ array = @technologies.map(&:capitalize)
144
+ return '' if array.nil?
145
+ return array.join if array.size <= 1
146
+ return array.join(' and ') if array.size == 2
147
+
148
+ "#{array[0..-2].join(', ')}, and #{array.last}"
127
149
  end
128
150
  end
129
151
  end
@@ -0,0 +1,221 @@
1
+ require_relative '../const/file'
2
+ require_relative '../const/yaml'
3
+ require_relative '../enum/option'
4
+ require_relative '../enum/technology'
5
+
6
+ require 'yaml'
7
+ require 'json'
8
+
9
+ module Package
10
+ module Audit
11
+ class ConfigCleaner # rubocop:disable Metrics/ClassLength
12
+ def initialize(dir, config, all_packages, options)
13
+ @dir = dir
14
+ @config = config
15
+ @all_packages = all_packages
16
+ @options = options
17
+ @config_file_path = determine_config_file_path
18
+ @removed_packages = []
19
+ end
20
+
21
+ def run
22
+ return unless @config && File.exist?(@config_file_path)
23
+
24
+ cleaned_config = clean_config
25
+
26
+ return unless config_changed?(cleaned_config)
27
+
28
+ write_config_file(cleaned_config)
29
+ print_summary unless @options[Enum::Option::FORMAT]
30
+ end
31
+
32
+ attr_reader :removed_packages
33
+
34
+ private
35
+
36
+ def determine_config_file_path
37
+ if @options[Enum::Option::CONFIG].nil?
38
+ "#{@dir}/#{Const::File::CONFIG}"
39
+ else
40
+ @options[Enum::Option::CONFIG]
41
+ end
42
+ end
43
+
44
+ def clean_config
45
+ return {} unless @config
46
+
47
+ cleaned = {}
48
+
49
+ if @config[Const::YAML::TECHNOLOGY]
50
+ cleaned[Const::YAML::TECHNOLOGY] = {}
51
+
52
+ # Sort technologies alphabetically to ensure consistent ordering
53
+ @config[Const::YAML::TECHNOLOGY].sort.each do |technology, packages|
54
+ cleaned_packages = clean_packages_for_technology(technology, packages)
55
+ cleaned[Const::YAML::TECHNOLOGY][technology] = cleaned_packages unless cleaned_packages.empty?
56
+ end
57
+
58
+ # Remove the technology key if no technologies have any packages
59
+ cleaned.delete(Const::YAML::TECHNOLOGY) if cleaned[Const::YAML::TECHNOLOGY].empty?
60
+ end
61
+
62
+ cleaned
63
+ end
64
+
65
+ def clean_packages_for_technology(technology, packages)
66
+ return {} unless packages.is_a?(Hash)
67
+
68
+ current_packages = current_packages_for_technology(technology)
69
+ cleaned_packages = {}
70
+
71
+ packages.each do |package_name, package_config|
72
+ next unless package_config.is_a?(Hash)
73
+
74
+ if should_keep_package?(package_name, package_config, current_packages)
75
+ cleaned_packages[package_name] = sort_package_config(package_config)
76
+ else
77
+ track_removed_package(technology, package_name, package_config)
78
+ end
79
+ end
80
+
81
+ # Sort package names alphabetically
82
+ cleaned_packages.sort.to_h
83
+ end
84
+
85
+ def current_packages_for_technology(technology)
86
+ @all_packages.select { |pkg| pkg.technology == technology }
87
+ .to_h { |pkg| [pkg.name, pkg.version] }
88
+ end
89
+
90
+ def should_keep_package?(package_name, package_config, current_packages)
91
+ config_version = package_config[Const::YAML::VERSION]
92
+ current_version = current_packages[package_name]
93
+
94
+ # Keep the package if it exists and the version matches
95
+ current_version && config_version == current_version
96
+ end
97
+
98
+ def sort_package_config(package_config)
99
+ sorted_config = {}
100
+
101
+ # Add version first if it exists
102
+ if package_config[Const::YAML::VERSION]
103
+ sorted_config[Const::YAML::VERSION] =
104
+ package_config[Const::YAML::VERSION]
105
+ end
106
+
107
+ # Add other keys in alphabetical order
108
+ other_keys = (package_config.keys - [Const::YAML::VERSION]).sort
109
+ other_keys.each do |key|
110
+ sorted_config[key] = package_config[key]
111
+ end
112
+
113
+ sorted_config
114
+ end
115
+
116
+ def track_removed_package(technology, package_name, package_config)
117
+ @removed_packages << {
118
+ technology: technology,
119
+ name: package_name,
120
+ version: package_config[Const::YAML::VERSION],
121
+ reason: determine_removal_reason(package_name, package_config)
122
+ }
123
+ end
124
+
125
+ def determine_removal_reason(package_name, package_config)
126
+ technology = find_technology_for_package(package_name)
127
+ return 'unknown reason' unless technology
128
+
129
+ current_packages = current_packages_for_technology(technology)
130
+ config_version = package_config[Const::YAML::VERSION]
131
+ current_version = current_packages[package_name]
132
+
133
+ determine_reason_based_on_versions(package_name, technology, config_version, current_version)
134
+ end
135
+
136
+ def find_technology_for_package(package_name)
137
+ @config[Const::YAML::TECHNOLOGY].each do |tech, packages|
138
+ return tech if packages.key?(package_name)
139
+ end
140
+ nil
141
+ end
142
+
143
+ def determine_reason_based_on_versions(package_name, technology, config_version, current_version)
144
+ if current_version.nil?
145
+ determine_reason_for_missing_package(package_name, technology)
146
+ elsif config_version != current_version
147
+ "version changed from #{config_version} to #{current_version}"
148
+ else
149
+ 'unknown reason'
150
+ end
151
+ end
152
+
153
+ def determine_reason_for_missing_package(package_name, technology)
154
+ if package_exists_in_project_files?(package_name, technology)
155
+ 'package version has changed'
156
+ else
157
+ 'package no longer exists'
158
+ end
159
+ end
160
+
161
+ def package_exists_in_project_files?(package_name, technology)
162
+ case technology
163
+ when Enum::Technology::RUBY
164
+ package_exists_in_gemfile?(package_name)
165
+ when Enum::Technology::NODE
166
+ package_exists_in_package_json?(package_name)
167
+ else
168
+ false
169
+ end
170
+ end
171
+
172
+ def package_exists_in_gemfile?(package_name)
173
+ gemfile_path = "#{@dir}/#{Const::File::GEMFILE}"
174
+ return false unless File.exist?(gemfile_path)
175
+
176
+ gemfile_content = File.read(gemfile_path)
177
+ # Check for gem declarations with single or double quotes
178
+ gemfile_content.match?(/^\s*gem\s+['"]#{Regexp.escape(package_name)}['"]/)
179
+ end
180
+
181
+ def package_exists_in_package_json?(package_name)
182
+ package_json_path = "#{@dir}/#{Const::File::PACKAGE_JSON}"
183
+ return false unless File.exist?(package_json_path)
184
+
185
+ begin
186
+ package_json = JSON.parse(File.read(package_json_path))
187
+ dependencies = package_json['dependencies'] || {}
188
+ dev_dependencies = package_json['devDependencies'] || {}
189
+
190
+ dependencies.key?(package_name) || dev_dependencies.key?(package_name)
191
+ rescue JSON::ParserError
192
+ false
193
+ end
194
+ end
195
+
196
+ def config_changed?(cleaned_config)
197
+ # Compare YAML representations to detect key reordering
198
+ cleaned_config.to_yaml != @config.to_yaml
199
+ end
200
+
201
+ def write_config_file(cleaned_config)
202
+ File.write(@config_file_path, cleaned_config.to_yaml)
203
+ end
204
+
205
+ def print_summary
206
+ return if @removed_packages.empty?
207
+
208
+ puts
209
+ puts "Cleaned up #{@removed_packages.count} package(s) from #{File.basename(@config_file_path)}:"
210
+
211
+ # Sort by technology then by name for consistent output
212
+ @removed_packages.sort_by { |pkg| [pkg[:technology], pkg[:name]] }.each do |removed_package|
213
+ package_info = "#{removed_package[:name]}@#{removed_package[:version]}"
214
+ tech_info = "(#{removed_package[:technology]})"
215
+ reason = removed_package[:reason]
216
+ puts " - #{package_info} #{tech_info}: #{reason}"
217
+ end
218
+ end
219
+ end
220
+ end
221
+ end
@@ -19,7 +19,7 @@ module Package
19
19
  @thread = Thread.new do
20
20
  step = 0
21
21
  while @running
22
- if @running && (ENV['RUBY_ENV'] != 'test' && ENV['RACK_ENV'] != 'test')
22
+ if @running && ENV['RUBY_ENV'] != 'test' && ENV['RACK_ENV'] != 'test'
23
23
  print "\r#{@message} #{STATES[step % STATES.length]}"
24
24
  end
25
25
  sleep ANIMATION_SPEED
@@ -18,18 +18,18 @@ module Package
18
18
 
19
19
  def self.vulnerable(technology, cmd)
20
20
  printf("%<info>s\n%<cmd>s\n\n",
21
- info: Util::BashColor.blue("To get more information about the #{technology} vulnerabilities run:"),
21
+ info: Util::BashColor.blue("For more information about #{technology.capitalize} vulnerabilities run:"),
22
22
  cmd: Util::BashColor.magenta(" > #{cmd}"))
23
23
  end
24
24
 
25
25
  def self.total(technology, report, pkgs, ignored_pkgs)
26
26
  if ignored_pkgs.any?
27
- puts Util::BashColor.cyan("Found a total of #{pkgs.length} #{technology} packages " \
27
+ puts Util::BashColor.cyan("Found a total of #{pkgs.length} #{technology.capitalize} packages " \
28
28
  "(#{ignored_pkgs.length} ignored).\n")
29
29
  elsif pkgs.any?
30
- puts Util::BashColor.cyan("Found a total of #{pkgs.length} #{technology} packages.\n")
30
+ puts Util::BashColor.cyan("Found a total of #{pkgs.length} #{technology.capitalize} packages.\n")
31
31
  else
32
- puts Util::BashColor.green("There are no #{report} #{technology} packages!\n")
32
+ puts Util::BashColor.green("There are no #{report} #{technology.capitalize} packages!\n")
33
33
  end
34
34
  end
35
35
 
@@ -66,10 +66,11 @@ module Package
66
66
  print status_message(stats)
67
67
  print Util::BashColor.cyan(' \\') if format == Enum::Format::MARKDOWN
68
68
  puts
69
- puts Util::BashColor.green("There are no deprecated, outdated or vulnerable #{technology} " \
69
+ puts Util::BashColor.green("There are no deprecated, outdated or vulnerable #{technology.capitalize} " \
70
70
  "packages (#{ignored_pkgs.length} ignored)!\n")
71
71
  else
72
- puts Util::BashColor.green("There are no deprecated, outdated or vulnerable #{technology} packages!\n")
72
+ puts Util::BashColor.green("There are no deprecated, outdated or vulnerable #{technology.capitalize} " \
73
+ "packages!\n")
73
74
  end
74
75
  end
75
76
 
@@ -1,5 +1,5 @@
1
1
  module Package
2
2
  module Audit
3
- VERSION = '0.6.0'
3
+ VERSION = '0.6.1'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: package-audit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.6.1
5
5
  platform: ruby
6
6
  authors:
7
- - Tactica Communications Inc.
8
- autorequire:
7
+ - Vadim Kononov
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2024-02-03 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: bundler-audit
@@ -41,7 +40,7 @@ dependencies:
41
40
  description: A useful tool for patch management and prioritization, package-audit
42
41
  produces a list of dependencies that are outdated, deprecated or have security vulnerabilities.
43
42
  email:
44
- - support@tactica.ca
43
+ - vadim@konoson.com
45
44
  executables:
46
45
  - package-audit
47
46
  extensions: []
@@ -78,6 +77,7 @@ files:
78
77
  - lib/package/audit/ruby/gem_meta_data.rb
79
78
  - lib/package/audit/ruby/vulnerability_finder.rb
80
79
  - lib/package/audit/services/command_parser.rb
80
+ - lib/package/audit/services/config_cleaner.rb
81
81
  - lib/package/audit/services/duplicate_package_merger.rb
82
82
  - lib/package/audit/services/package_filter.rb
83
83
  - lib/package/audit/services/package_finder.rb
@@ -90,56 +90,13 @@ files:
90
90
  - lib/package/audit/util/spinner.rb
91
91
  - lib/package/audit/util/summary_printer.rb
92
92
  - lib/package/audit/version.rb
93
- - sig/package/audit/cli.rbs
94
- - sig/package/audit/const/cmd.rbs
95
- - sig/package/audit/const/fields.rbs
96
- - sig/package/audit/const/file.rbs
97
- - sig/package/audit/const/time.rbs
98
- - sig/package/audit/const/yaml.rbs
99
- - sig/package/audit/enum/format.rbs
100
- - sig/package/audit/enum/group.rbs
101
- - sig/package/audit/enum/option.rbs
102
- - sig/package/audit/enum/report.rbs
103
- - sig/package/audit/enum/risk_explanation.rbs
104
- - sig/package/audit/enum/risk_type.rbs
105
- - sig/package/audit/enum/technology.rbs
106
- - sig/package/audit/enum/vulnerability_type.rbs
107
- - sig/package/audit/formatter/base.rbs
108
- - sig/package/audit/formatter/risk_printer.rbs
109
- - sig/package/audit/formatter/version_date.rbs
110
- - sig/package/audit/formatter/version_printer.rbs
111
- - sig/package/audit/formatter/vulnerability.rbs
112
- - sig/package/audit/models/package.rbs
113
- - sig/package/audit/models/risk.rbs
114
- - sig/package/audit/npm/node_collection.rbs
115
- - sig/package/audit/npm/npm_meta_data.rbs
116
- - sig/package/audit/npm/vulnerability_finder.rbs
117
- - sig/package/audit/npm/yarn_lock_parser.rbs
118
- - sig/package/audit/ruby/bundler_specs.rbs
119
- - sig/package/audit/ruby/gem_collection.rbs
120
- - sig/package/audit/ruby/gem_meta_data.rbs
121
- - sig/package/audit/ruby/vulnerability_finder.rbs
122
- - sig/package/audit/services/command_parser.rbs
123
- - sig/package/audit/services/duplicate_package_merger.rbs
124
- - sig/package/audit/services/package_filter.rbs
125
- - sig/package/audit/services/package_finder.rbs
126
- - sig/package/audit/services/package_printer.rbs
127
- - sig/package/audit/services/risk_calculator.rbs
128
- - sig/package/audit/technology/detector.rbs
129
- - sig/package/audit/technology/validator.rbs
130
- - sig/package/audit/util/bash_color.rbs
131
- - sig/package/audit/util/risk_legend.rbs
132
- - sig/package/audit/util/spinner.rbs
133
- - sig/package/audit/util/summary_printer.rbs
134
- - sig/package/audit/version.rbs
135
- homepage: https://github.com/tactica/package-audit
93
+ homepage: https://github.com/vkononov/package-audit
136
94
  licenses:
137
95
  - MIT
138
96
  metadata:
139
- homepage_uri: https://github.com/tactica/package-audit
140
- source_code_uri: https://github.com/tactica/package-audit
97
+ homepage_uri: https://github.com/vkononov/package-audit
98
+ source_code_uri: https://github.com/vkononov/package-audit
141
99
  rubygems_mfa_required: 'true'
142
- post_install_message:
143
100
  rdoc_options: []
144
101
  require_paths:
145
102
  - lib
@@ -154,8 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
154
111
  - !ruby/object:Gem::Version
155
112
  version: '0'
156
113
  requirements: []
157
- rubygems_version: 3.4.22
158
- signing_key:
114
+ rubygems_version: 3.6.7
159
115
  specification_version: 4
160
116
  summary: A helper tool to find outdated, deprecated and vulnerable dependencies.
161
117
  test_files: []
@@ -1,35 +0,0 @@
1
- module Package
2
- module Audit
3
- class CLI
4
- def self.exit_on_failure?: -> bool
5
-
6
- def default: (String) -> void
7
-
8
- def deprecated: (String) -> void
9
-
10
- def outdated: (String) -> void
11
-
12
- def report: (String) -> void
13
-
14
- def respond_to_missing?: -> bool
15
-
16
- def risk: -> void
17
-
18
- def version: -> void
19
-
20
- def vulnerable: (String) -> void
21
-
22
- private
23
-
24
- def exit_with_error: (String) -> void
25
-
26
- def exit_with_success: (String) -> void
27
-
28
- def print_total: (Integer) -> void
29
-
30
- def print_vulnerability_info: (String) -> void
31
-
32
- def within_rescue_block: (String) { () -> void } -> void
33
- end
34
- end
35
- end
@@ -1,14 +0,0 @@
1
- module Package
2
- module Audit
3
- module Const
4
- module Cmd
5
- BUNDLE_AUDIT: String
6
- BUNDLE_AUDIT_JSON: String
7
- NPM_AUDIT: String
8
- NPM_AUDIT_JSON: String
9
- YARN_AUDIT: String
10
- YARN_AUDIT_JSON: String
11
- end
12
- end
13
- end
14
- end
@@ -1,11 +0,0 @@
1
- module Package
2
- module Audit
3
- module Const
4
- module Fields
5
- AVAILABLE: Array[Symbol]
6
- DEFAULT: Array[Symbol]
7
- HEADERS: Hash[Symbol, String]
8
- end
9
- end
10
- end
11
- end