package-audit 0.3.0 → 0.4.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 +4 -4
- data/lib/package/audit/cli.rb +32 -32
- data/lib/package/audit/const/fields.rb +4 -4
- data/lib/package/audit/const/file.rb +1 -0
- data/lib/package/audit/const/yaml.rb +13 -0
- data/lib/package/audit/enum/option.rb +13 -0
- data/lib/package/audit/enum/report.rb +12 -0
- data/lib/package/audit/enum/technology.rb +14 -0
- data/lib/package/audit/formatter/risk.rb +1 -1
- data/lib/package/audit/formatter/version.rb +1 -1
- data/lib/package/audit/formatter/version_date.rb +1 -1
- data/lib/package/audit/formatter/vulnerability.rb +1 -1
- data/lib/package/audit/{package.rb → models/package.rb} +7 -6
- data/lib/package/audit/npm/node_collection.rb +21 -10
- data/lib/package/audit/npm/vulnerability_finder.rb +1 -1
- data/lib/package/audit/npm/yarn_lock_parser.rb +1 -1
- data/lib/package/audit/ruby/bundler_specs.rb +1 -1
- data/lib/package/audit/ruby/gem_collection.rb +23 -6
- data/lib/package/audit/ruby/gem_meta_data.rb +1 -1
- data/lib/package/audit/ruby/vulnerability_finder.rb +1 -1
- data/lib/package/audit/services/command_parser.rb +103 -0
- data/lib/package/audit/services/package_filter.rb +39 -0
- data/lib/package/audit/services/package_finder.rb +58 -0
- data/lib/package/audit/{printer.rb → services/package_printer.rb} +12 -11
- data/lib/package/audit/{risk_calculator.rb → services/risk_calculator.rb} +8 -4
- data/lib/package/audit/technology/detector.rb +40 -0
- data/lib/package/audit/technology/validator.rb +56 -0
- data/lib/package/audit/util/summary_printer.rb +20 -9
- data/lib/package/audit/version.rb +1 -1
- data/sig/package/audit/cli.rbs +2 -0
- data/sig/package/audit/const/fields.rbs +2 -1
- data/sig/package/audit/const/file.rbs +1 -0
- data/sig/package/audit/const/yaml.rbs +13 -0
- data/sig/package/audit/enum/option.rbs +13 -0
- data/sig/package/audit/enum/report.rbs +12 -0
- data/sig/package/audit/enum/technology.rbs +12 -0
- data/sig/package/audit/{package.rbs → models/package.rbs} +3 -1
- data/sig/package/audit/{risk.rbs → models/risk.rbs} +1 -1
- data/sig/package/audit/npm/node_collection.rbs +4 -5
- data/sig/package/audit/npm/vulnerability_finder.rbs +1 -1
- data/sig/package/audit/ruby/gem_collection.rbs +4 -1
- data/sig/package/audit/services/command_parser.rbs +31 -0
- data/sig/package/audit/services/package_filter.rbs +19 -0
- data/sig/package/audit/services/package_finder.rbs +23 -0
- data/sig/package/audit/{printer.rbs → services/package_printer.rbs} +3 -3
- data/sig/package/audit/technology/detector.rbs +19 -0
- data/sig/package/audit/technology/validator.rbs +19 -0
- data/sig/package/audit/util/summary_printer.rbs +5 -5
- metadata +30 -14
- data/lib/package/audit/command_service.rb +0 -187
- data/sig/package/audit/command_service.rbs +0 -29
- /data/lib/package/audit/{risk.rb → models/risk.rb} +0 -0
- /data/lib/package/audit/{duplicate_package_merger.rb → services/duplicate_package_merger.rb} +0 -0
- /data/sig/package/audit/{duplicate_package_merger.rbs → services/duplicate_package_merger.rbs} +0 -0
- /data/sig/package/audit/{risk_calculator.rbs → services/risk_calculator.rbs} +0 -0
@@ -1,27 +1,28 @@
|
|
1
|
-
require_relative 'const/fields'
|
2
|
-
require_relative '
|
3
|
-
require_relative 'formatter/
|
4
|
-
require_relative 'formatter/
|
5
|
-
require_relative 'formatter/
|
1
|
+
require_relative '../const/fields'
|
2
|
+
require_relative '../enum/option'
|
3
|
+
require_relative '../formatter/risk'
|
4
|
+
require_relative '../formatter/version'
|
5
|
+
require_relative '../formatter/version_date'
|
6
|
+
require_relative '../formatter/vulnerability'
|
6
7
|
|
7
8
|
module Package
|
8
9
|
module Audit
|
9
|
-
class
|
10
|
+
class PackagePrinter
|
10
11
|
BASH_FORMATTING_REGEX = /\e\[\d+(?:;\d+)*m/
|
11
12
|
|
12
13
|
COLUMN_GAP = 2
|
13
14
|
|
14
|
-
def initialize(
|
15
|
-
@pkgs = pkgs
|
15
|
+
def initialize(options, pkgs)
|
16
16
|
@options = options
|
17
|
+
@pkgs = pkgs
|
17
18
|
end
|
18
19
|
|
19
20
|
def print(fields)
|
20
21
|
check_fields(fields)
|
21
22
|
return if @pkgs.empty?
|
22
23
|
|
23
|
-
if @options[
|
24
|
-
csv(fields, exclude_headers: @options[
|
24
|
+
if @options[Enum::Option::CSV]
|
25
|
+
csv(fields, exclude_headers: @options[Enum::Option::CSV_EXCLUDE_HEADERS])
|
25
26
|
else
|
26
27
|
pretty(fields)
|
27
28
|
end
|
@@ -38,7 +39,7 @@ module Package
|
|
38
39
|
"Available fields names are: #{Const::Fields::ALL}."
|
39
40
|
end
|
40
41
|
|
41
|
-
def pretty(fields = Const::Fields::
|
42
|
+
def pretty(fields = Const::Fields::ALL) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
42
43
|
# find the maximum length of each field across all the packages so we know how many
|
43
44
|
# characters of horizontal space to allocate for each field when printing
|
44
45
|
fields.each do |key|
|
@@ -1,4 +1,7 @@
|
|
1
|
-
require_relative 'const/time'
|
1
|
+
require_relative '../const/time'
|
2
|
+
require_relative '../enum/vulnerability_type'
|
3
|
+
|
4
|
+
require 'time'
|
2
5
|
|
3
6
|
module Package
|
4
7
|
module Audit
|
@@ -62,12 +65,13 @@ module Package
|
|
62
65
|
end
|
63
66
|
|
64
67
|
def assess_deprecation_risks
|
68
|
+
risk = Risk.new(Enum::RiskType::MEDIUM, Enum::RiskExplanation::POTENTIAL_DEPRECATION)
|
69
|
+
return [risk] if @pkg.latest_version_date.nil?
|
70
|
+
|
65
71
|
risks = []
|
66
72
|
seconds_since_date = (Time.now - Time.parse(@pkg.latest_version_date)).to_i
|
67
73
|
|
68
|
-
if seconds_since_date >= Const::Time::SECONDS_ELAPSED_TO_BE_OUTDATED
|
69
|
-
risks << Risk.new(Enum::RiskType::MEDIUM, Enum::RiskExplanation::POTENTIAL_DEPRECATION)
|
70
|
-
end
|
74
|
+
risks << risk if seconds_since_date >= Const::Time::SECONDS_ELAPSED_TO_BE_OUTDATED
|
71
75
|
risks
|
72
76
|
end
|
73
77
|
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require_relative '../const/cmd'
|
2
|
+
require_relative '../const/file'
|
3
|
+
require_relative '../enum/report'
|
4
|
+
require_relative '../enum/technology'
|
5
|
+
|
6
|
+
require 'yaml'
|
7
|
+
|
8
|
+
module Package
|
9
|
+
module Audit
|
10
|
+
module Technology
|
11
|
+
class Detector
|
12
|
+
def initialize(dir)
|
13
|
+
@dir = dir
|
14
|
+
end
|
15
|
+
|
16
|
+
def detect
|
17
|
+
technologies = []
|
18
|
+
technologies << Enum::Technology::RUBY if ruby?
|
19
|
+
technologies << Enum::Technology::NODE if node?
|
20
|
+
technologies.sort
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def node?
|
26
|
+
package_json_present = File.exist?("#{@dir}/#{Const::File::PACKAGE_JSON}")
|
27
|
+
package_lock_json_present = File.exist?("#{@dir}/#{Const::File::PACKAGE_LOCK_JSON}")
|
28
|
+
yarn_lock_present = File.exist?("#{@dir}/#{Const::File::YARN_LOCK}")
|
29
|
+
package_json_present && (package_lock_json_present || yarn_lock_present)
|
30
|
+
end
|
31
|
+
|
32
|
+
def ruby?
|
33
|
+
gemfile_present = File.exist?("#{@dir}/#{Const::File::GEMFILE}")
|
34
|
+
gemfile_lock_present = File.exist?("#{@dir}/#{Const::File::GEMFILE_LOCK}")
|
35
|
+
gemfile_present && gemfile_lock_present
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require_relative '../const/file'
|
2
|
+
require_relative '../enum/technology'
|
3
|
+
|
4
|
+
module Package
|
5
|
+
module Audit
|
6
|
+
module Technology
|
7
|
+
class Validator
|
8
|
+
def initialize(dir)
|
9
|
+
@dir = dir
|
10
|
+
end
|
11
|
+
|
12
|
+
def validate!(technology)
|
13
|
+
case technology
|
14
|
+
when Enum::Technology::NODE
|
15
|
+
validate_node!
|
16
|
+
when Enum::Technology::RUBY
|
17
|
+
validate_ruby!
|
18
|
+
else
|
19
|
+
raise ArgumentError, "\"#{technology}\" is not a supported technology, " \
|
20
|
+
"use one of #{Enum::Technology.all}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def validate_node!
|
27
|
+
package_json_present = File.exist?("#{@dir}/#{Const::File::PACKAGE_JSON}")
|
28
|
+
package_lock_json_present = File.exist?("#{@dir}/#{Const::File::PACKAGE_LOCK_JSON}")
|
29
|
+
yarn_lock_present = File.exist?("#{@dir}/#{Const::File::YARN_LOCK}")
|
30
|
+
|
31
|
+
unless package_json_present
|
32
|
+
puts Util::BashColor.red("\"#{Const::File::PACKAGE_JSON}\" was not found in #{@dir}")
|
33
|
+
end
|
34
|
+
unless package_lock_json_present || yarn_lock_present
|
35
|
+
puts Util::BashColor.red("\"#{Const::File::PACKAGE_LOCK_JSON}\" or \"#{Const::File::YARN_LOCK}\" " \
|
36
|
+
"was not found in #{@dir}")
|
37
|
+
end
|
38
|
+
|
39
|
+
exit 1 unless package_json_present && (package_lock_json_present || yarn_lock_present)
|
40
|
+
end
|
41
|
+
|
42
|
+
def validate_ruby!
|
43
|
+
gemfile_present = File.exist?("#{@dir}/#{Const::File::GEMFILE}")
|
44
|
+
gemfile_lock_present = File.exist?("#{@dir}/#{Const::File::GEMFILE_LOCK}")
|
45
|
+
|
46
|
+
puts Util::BashColor.red("\"#{Const::File::GEMFILE}\" was not found in #{@dir}") unless gemfile_present
|
47
|
+
unless gemfile_lock_present
|
48
|
+
puts Util::BashColor.red("\"#{Const::File::GEMFILE_LOCK}\" was not found in #{@dir}")
|
49
|
+
end
|
50
|
+
|
51
|
+
exit 1 unless gemfile_present && gemfile_lock_present
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -5,7 +5,7 @@ module Package
|
|
5
5
|
module Audit
|
6
6
|
module Util
|
7
7
|
module SummaryPrinter
|
8
|
-
def self.
|
8
|
+
def self.all
|
9
9
|
printf("\n%<info>s\n%<cmd>s\n\n",
|
10
10
|
info: Util::BashColor.blue('To show how risk is calculated run:'),
|
11
11
|
cmd: Util::BashColor.magenta(' > package-audit risk'))
|
@@ -16,26 +16,37 @@ module Package
|
|
16
16
|
puts Util::BashColor.blue("Please contact the package author for more information about its status.\n")
|
17
17
|
end
|
18
18
|
|
19
|
-
def self.vulnerable(
|
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 #{
|
21
|
+
info: Util::BashColor.blue("To get more information about the #{technology} vulnerabilities run:"),
|
22
22
|
cmd: Util::BashColor.magenta(" > #{cmd}"))
|
23
23
|
end
|
24
24
|
|
25
|
-
def self.total(
|
26
|
-
|
25
|
+
def self.total(technology, report, pkgs, ignored_pkgs)
|
26
|
+
if ignored_pkgs.any?
|
27
|
+
puts Util::BashColor.cyan("Found a total of #{pkgs.length} #{technology} packages " \
|
28
|
+
"(#{ignored_pkgs.length} ignored).\n")
|
29
|
+
elsif pkgs.any?
|
30
|
+
puts Util::BashColor.cyan("Found a total of #{pkgs.length} #{technology} packages.\n")
|
31
|
+
else
|
32
|
+
puts Util::BashColor.green("There are no #{report} #{technology} packages!\n")
|
33
|
+
end
|
27
34
|
end
|
28
35
|
|
29
|
-
def self.statistics(
|
36
|
+
def self.statistics(technology, report, pkgs, ignored_pkgs)
|
30
37
|
outdated = pkgs.count(&:outdated?)
|
31
38
|
deprecated = pkgs.count(&:deprecated?)
|
32
39
|
vulnerable = pkgs.count(&:vulnerable?)
|
33
40
|
|
34
41
|
vulnerabilities = pkgs.sum { |pkg| pkg.vulnerabilities.length }
|
35
42
|
|
36
|
-
|
37
|
-
|
38
|
-
|
43
|
+
if pkgs.any?
|
44
|
+
puts Util::BashColor.cyan("#{vulnerable} vulnerable (#{vulnerabilities} vulnerabilities), " \
|
45
|
+
"#{outdated} outdated, #{deprecated} deprecated.")
|
46
|
+
total(technology, report, pkgs, ignored_pkgs)
|
47
|
+
else
|
48
|
+
puts Util::BashColor.green("There are no deprecated, outdated or vulnerable #{technology} packages!\n")
|
49
|
+
end
|
39
50
|
end
|
40
51
|
|
41
52
|
def self.risk # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
data/sig/package/audit/cli.rbs
CHANGED
@@ -3,17 +3,19 @@ module Package
|
|
3
3
|
class Package
|
4
4
|
@groups: Array[Symbol]
|
5
5
|
@risks: Array[Risk]
|
6
|
+
@technology: String
|
6
7
|
@vulnerabilities: Array[String]
|
7
8
|
|
8
9
|
attr_accessor groups: Array[Symbol]
|
9
10
|
attr_accessor latest_version: String
|
10
11
|
attr_accessor latest_version_date: String
|
11
12
|
attr_reader name: String
|
13
|
+
attr_reader technology: String
|
12
14
|
attr_reader version: String
|
13
15
|
attr_accessor version_date: String
|
14
16
|
attr_accessor vulnerabilities: Array[String]
|
15
17
|
|
16
|
-
def initialize: (String, String, **untyped) -> void
|
18
|
+
def initialize: (String, String, String, **untyped) -> void
|
17
19
|
|
18
20
|
def deprecated?: -> bool
|
19
21
|
|
@@ -2,18 +2,17 @@ module Package
|
|
2
2
|
module Audit
|
3
3
|
module Npm
|
4
4
|
class NodeCollection
|
5
|
-
PACKAGE_JSON: String
|
6
|
-
PACKAGE_LOCK: String
|
7
|
-
YARN_LOCK: String
|
8
|
-
|
9
5
|
@dir: String
|
6
|
+
@report: Symbol
|
10
7
|
|
11
|
-
def initialize: (String) -> void
|
8
|
+
def initialize: (String, Symbol) -> void
|
12
9
|
|
13
10
|
def all: -> Array[Package]
|
14
11
|
|
15
12
|
def deprecated: -> Array[Package]
|
16
13
|
|
14
|
+
def fetch: -> Array[Package]
|
15
|
+
|
17
16
|
def outdated: -> Array[Package]
|
18
17
|
|
19
18
|
def vulnerable: -> Array[Package]
|
@@ -3,13 +3,16 @@ module Package
|
|
3
3
|
module Ruby
|
4
4
|
class GemCollection
|
5
5
|
@dir: String
|
6
|
+
@report: Symbol
|
6
7
|
|
7
|
-
def initialize: (String) -> void
|
8
|
+
def initialize: (String, Symbol) -> void
|
8
9
|
|
9
10
|
def all: -> Array[Package]
|
10
11
|
|
11
12
|
def deprecated: -> Array[Package]
|
12
13
|
|
14
|
+
def fetch: -> Array[Package]
|
15
|
+
|
13
16
|
def outdated: (?include_implicit: bool) -> Array[Package]
|
14
17
|
|
15
18
|
def vulnerable: -> Array[Package]
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Package
|
2
|
+
module Audit
|
3
|
+
class CommandParser
|
4
|
+
@config: Hash[String, untyped]?
|
5
|
+
@dir: String
|
6
|
+
@options: Hash[String, untyped]
|
7
|
+
@report: Symbol
|
8
|
+
@technologies: Array[String]
|
9
|
+
|
10
|
+
def initialize: (String, Hash[String, untyped], Symbol) -> void
|
11
|
+
|
12
|
+
def run: -> bool
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def learn_more_command: (String) -> String?
|
17
|
+
|
18
|
+
def parse_config_file: -> Hash[String, untyped]?
|
19
|
+
|
20
|
+
def parse_technologies: -> Array[String]
|
21
|
+
|
22
|
+
def print_disclaimer: (String) -> void
|
23
|
+
|
24
|
+
def print_results: (String, Array[Package], Array[Package]) -> void
|
25
|
+
|
26
|
+
def print_summary: (String, Array[Package], Array[Package]) -> void
|
27
|
+
|
28
|
+
def report_fields: -> Array[Symbol]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Package
|
2
|
+
module Audit
|
3
|
+
class PackageFilter
|
4
|
+
@config: Hash[String, untyped]?
|
5
|
+
|
6
|
+
def initialize: (Hash[String, untyped]?) -> void
|
7
|
+
|
8
|
+
def ignored?: (Package) -> bool
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def ignore_package?: (Package, Hash[String, untyped]?) -> bool
|
13
|
+
|
14
|
+
def pkg_version_in_config?: (Package, Hash[String, untyped]?) -> bool
|
15
|
+
|
16
|
+
def pkg_yaml_from_config: (Package) -> Hash[String, untyped]?
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Package
|
2
|
+
module Audit
|
3
|
+
class PackageFinder
|
4
|
+
@config: Hash[String, untyped]?
|
5
|
+
@dir: String
|
6
|
+
@report: Symbol
|
7
|
+
|
8
|
+
def initialize: (Hash[String, untyped]?, String, Symbol) -> void
|
9
|
+
|
10
|
+
def run: (String) -> Array[Array[Package]]
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def filter_pkgs_based_on_config: (Array[Package]) -> Array[Package]
|
15
|
+
|
16
|
+
def find_by_technology: (String) -> Array[Package]
|
17
|
+
|
18
|
+
def find_node: -> Array[Package]
|
19
|
+
|
20
|
+
def find_ruby: -> Array[Package]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -1,14 +1,14 @@
|
|
1
1
|
module Package
|
2
2
|
module Audit
|
3
|
-
class
|
3
|
+
class PackagePrinter
|
4
4
|
BASH_FORMATTING_REGEX: Regexp
|
5
5
|
COLUMN_GAP: Integer
|
6
6
|
CSV_HEADERS: Hash[Symbol, String]
|
7
7
|
|
8
8
|
@pkgs: Array[Package]
|
9
|
-
@options: Hash[
|
9
|
+
@options: Hash[String, untyped]
|
10
10
|
|
11
|
-
def initialize: (
|
11
|
+
def initialize: (Hash[String, untyped], Array[Package]) -> void
|
12
12
|
|
13
13
|
def print: (Array[Symbol]) -> void
|
14
14
|
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Package
|
2
|
+
module Audit
|
3
|
+
module Technology
|
4
|
+
class Detector
|
5
|
+
@dir: String
|
6
|
+
|
7
|
+
def initialize: (String) -> void
|
8
|
+
|
9
|
+
def detect: -> Array[String]
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def node?: -> bool
|
14
|
+
|
15
|
+
def ruby?: -> bool
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Package
|
2
|
+
module Audit
|
3
|
+
module Technology
|
4
|
+
class Validator
|
5
|
+
@dir: String
|
6
|
+
|
7
|
+
def initialize: (String) -> void
|
8
|
+
|
9
|
+
def validate!: (String) -> void
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def validate_node!: -> void
|
14
|
+
|
15
|
+
def validate_ruby!: -> void
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -2,17 +2,17 @@ module Package
|
|
2
2
|
module Audit
|
3
3
|
module Util
|
4
4
|
module SummaryPrinter
|
5
|
-
def self.
|
5
|
+
def self.all: -> void
|
6
6
|
|
7
|
-
def self.
|
7
|
+
def self.deprecated: -> void
|
8
8
|
|
9
9
|
def self.risk: -> void
|
10
10
|
|
11
|
-
def self.statistics: (String, Array[Package]) -> void
|
11
|
+
def self.statistics: (String, Symbol, Array[Package], Array[Package]) -> void
|
12
12
|
|
13
|
-
def self.total: (String, Array[Package]) -> void
|
13
|
+
def self.total: (String, Symbol, Array[Package], Array[Package]) -> void
|
14
14
|
|
15
|
-
def self.vulnerable: (String, String) -> void
|
15
|
+
def self.vulnerable: (String, String?) -> void
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|