pronto-bundler_audit 0.2.1 → 0.3.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: 14598d0b688654057c7bf84f388f5d9881394d916c89e93aabed9f359046fa4e
4
- data.tar.gz: aebe7dc2245ad8459e002bb2e2454343bec3c0f6906ce67b97d310dadeb36cca
3
+ metadata.gz: 2a6328fffd859750def2c69f570ea970ecc44aa1b31362dfa03b5933cde49201
4
+ data.tar.gz: c6c226e11867996c7d19d53089a31e20b87acaebe3593713f11d310f7e1b602b
5
5
  SHA512:
6
- metadata.gz: 107cc7d4a03d1db7cca881a5a0e3f8fc63efa57f43aeb328fc65bcd75eb569e89d5a77d5fd968c02b9904fd7983a5430ce5535e1985c566d061883aba0017369
7
- data.tar.gz: 3047f3525a76613c0199c05353c4a2342434a07e689c586dfd1586a70c533cd263879567b7ebc8f9549bb70f618a83340014316589f0c3710cff78df50cc9d64
6
+ metadata.gz: df67a7343d90292e9b15fdfeb6c75eab64b76b27a98ee1feffb3ac9b2c1ef3f0e20822048a595018904d19655c8c82142635644409e01faaee3fa313fccc5826
7
+ data.tar.gz: 167db3c4bfbd04bec6b25d519f0fd060809de610f899d8e3cc166601baac28ffcc512129ab02496305899df4b7f192fc77a274352f4cc2fcdfcb8f6c846e5edb
data/.rubocop ADDED
@@ -0,0 +1,4 @@
1
+ --display-cop-names
2
+ --display-style-guide
3
+ --extra-details
4
+ --format=fuubar
data/.rubocop.yml ADDED
@@ -0,0 +1,156 @@
1
+ AllCops:
2
+ UseCache: true
3
+ DisplayCopNames: true
4
+ DisplayStyleGuide: true
5
+ ExtraDetails: false
6
+ TargetRubyVersion: 2.5.3
7
+
8
+ Layout/ClassStructure:
9
+ Enabled: true
10
+ Categories:
11
+ module_inclusion:
12
+ - extend
13
+ - include
14
+ - prepend
15
+ attributes:
16
+ - attr_accessor
17
+ - attr_reader
18
+ - attr_writer
19
+ ExpectedOrder:
20
+ - constants
21
+ - module_inclusion
22
+ - attributes
23
+ - public_class_methods
24
+ - initializer
25
+ - public_methods
26
+ - predicates
27
+ - protected_methods
28
+ - private_methods
29
+
30
+ Layout/DotPosition:
31
+ EnforcedStyle: trailing
32
+
33
+ Layout/EmptyLineAfterGuardClause:
34
+ Enabled: true
35
+
36
+ Layout/EndOfLine:
37
+ EnforcedStyle: lf
38
+
39
+ Layout/IndentFirstArgument:
40
+ EnforcedStyle: consistent_relative_to_receiver
41
+
42
+ Layout/IndentFirstArrayElement:
43
+ EnforcedStyle: consistent
44
+
45
+ Layout/IndentFirstHashElement:
46
+ EnforcedStyle: consistent
47
+
48
+ Layout/MultilineAssignmentLayout:
49
+ Enabled: true
50
+
51
+ Layout/MultilineMethodCallBraceLayout:
52
+ EnforcedStyle: same_line
53
+
54
+ Layout/MultilineMethodCallIndentation:
55
+ EnforcedStyle: indented_relative_to_receiver
56
+
57
+ Layout/MultilineMethodDefinitionBraceLayout:
58
+ EnforcedStyle: same_line
59
+
60
+ Layout/MultilineOperationIndentation:
61
+ Enabled: false # Waiting for e.g. `indented_relative_to_receiver`.
62
+
63
+ Lint/AmbiguousOperator:
64
+ Enabled: false # Conflicts with other rules.
65
+
66
+ Lint/AmbiguousRegexpLiteral:
67
+ Enabled: false # Conflicts with other rules.
68
+
69
+ Lint/Void:
70
+ CheckForMethodsWithNoSideEffects: true
71
+
72
+ Metrics/BlockLength:
73
+ ExcludedMethods:
74
+ - new
75
+ - describe # Tests
76
+ - context # Tests
77
+ - ips # Benchmarking
78
+
79
+ Metrics/ClassLength:
80
+ Exclude:
81
+ - "test/**/*"
82
+ - "lib/object_inspector/formatters/templating_formatter.rb"
83
+
84
+ Metrics/LineLength:
85
+ Max: 80
86
+ Exclude:
87
+ - "test/**/*"
88
+ - "object_inspector.gemspec"
89
+
90
+ Naming/UncommunicativeMethodParamName:
91
+ AllowedNames:
92
+ - a
93
+ - b
94
+
95
+ Style/Alias:
96
+ EnforcedStyle: prefer_alias_method
97
+
98
+ Style/BlockDelimiters:
99
+ Enabled: false # Reconsider later.
100
+
101
+ Style/ClassAndModuleChildren:
102
+ AutoCorrect: true
103
+ Exclude:
104
+ - "test/**/*"
105
+
106
+ Style/CollectionMethods:
107
+ Enabled: true
108
+ PreferredMethods:
109
+ collect: map
110
+ collect!: map!
111
+ find_all: select
112
+ detect: detect
113
+ inject: inject
114
+
115
+ Style/EmptyElse:
116
+ # It"s helpful to show intent by including a comment in an else block.
117
+ Enabled: false
118
+
119
+ Style/EmptyMethod:
120
+ EnforcedStyle: expanded
121
+
122
+ Style/ExpandPathArguments:
123
+ Exclude:
124
+ - "object_inspector.gemspec"
125
+
126
+ Style/FormatString:
127
+ Enabled: false # % notation with an Array just reads better sometimes.
128
+
129
+ Style/Lambda:
130
+ EnforcedStyle: literal
131
+
132
+ Style/NumericPredicate:
133
+ Enabled: false # Trying to be welcoming to earlier versions of Ruby.
134
+ # AutoCorrect: true
135
+
136
+ Style/RegexpLiteral:
137
+ EnforcedStyle: mixed
138
+
139
+ Style/RescueStandardError:
140
+ EnforcedStyle: implicit
141
+
142
+ Style/ReturnNil:
143
+ Enabled: true
144
+
145
+ Style/StringMethods:
146
+ Enabled: true
147
+
148
+ Style/SingleLineMethods:
149
+ Exclude:
150
+ - "test/**/*_test.rb"
151
+
152
+ Style/StringLiterals:
153
+ EnforcedStyle: double_quotes
154
+
155
+ Style/StringLiteralsInInterpolation:
156
+ EnforcedStyle: double_quotes
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ### 0.3.0 - 2019-05-03
2
+ - Internal rewrite into smaller objects with full test coverage
3
+ - Switch to using the verbose advisory formatter by default
4
+
1
5
  ### 0.2.1 - 2019-04-30
2
6
  - Fix handling of the Pronto::Git::Patches collection in Pronto::BundlerAudit#run
3
7
  - Ensure an Array is returned by Pronto::BundlerAudit#run, as expected by Pronto
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source "https://rubygems.org"
2
4
 
3
5
  # Specify your gem's dependencies in pronto-bundler_audit.gemspec
data/Gemfile.lock CHANGED
@@ -1,14 +1,14 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pronto-bundler_audit (0.2.1)
4
+ pronto-bundler_audit (0.3.0)
5
5
  bundler-audit (~> 0)
6
6
  pronto (~> 0)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- addressable (2.5.2)
11
+ addressable (2.6.0)
12
12
  public_suffix (>= 2.0.2, < 4.0)
13
13
  ansi (1.5.0)
14
14
  ast (2.4.0)
@@ -29,7 +29,6 @@ GEM
29
29
  multi_xml (>= 0.5.2)
30
30
  jaro_winkler (1.5.2)
31
31
  json (2.2.0)
32
- metaclass (0.0.4)
33
32
  method_source (0.9.2)
34
33
  mime-types (3.2.2)
35
34
  mime-types-data (~> 3.2015)
@@ -40,8 +39,7 @@ GEM
40
39
  builder
41
40
  minitest (>= 5.0)
42
41
  ruby-progressbar
43
- mocha (1.8.0)
44
- metaclass (~> 0.0.1)
42
+ much-stub (0.1.0)
45
43
  multi_xml (0.6.0)
46
44
  multipart-post (2.0.0)
47
45
  octokit (4.14.0)
@@ -65,7 +63,7 @@ GEM
65
63
  public_suffix (3.0.3)
66
64
  rainbow (3.0.0)
67
65
  rake (12.3.2)
68
- rubocop (0.68.0)
66
+ rubocop (0.68.1)
69
67
  jaro_winkler (~> 1.5.1)
70
68
  parallel (~> 1.10)
71
69
  parser (>= 2.5, != 2.5.1.1)
@@ -74,9 +72,9 @@ GEM
74
72
  unicode-display_width (>= 1.4.0, < 1.6)
75
73
  ruby-progressbar (1.10.0)
76
74
  rugged (0.28.1)
77
- sawyer (0.8.1)
78
- addressable (>= 2.3.5, < 2.6)
79
- faraday (~> 0.8, < 1.0)
75
+ sawyer (0.8.2)
76
+ addressable (>= 2.3.5)
77
+ faraday (> 0.8, < 2.0)
80
78
  simplecov (0.16.1)
81
79
  docile (~> 1.1)
82
80
  json (>= 1.8, < 3)
@@ -95,7 +93,7 @@ DEPENDENCIES
95
93
  byebug (~> 11)
96
94
  minitest (~> 5)
97
95
  minitest-reporters (~> 1)
98
- mocha (~> 1)
96
+ much-stub (~> 0)
99
97
  pronto-bundler_audit!
100
98
  pry (~> 0)
101
99
  pry-byebug (~> 3)
data/README.md CHANGED
@@ -64,7 +64,6 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
64
64
 
65
65
  ## TODO
66
66
 
67
- * Add more tests
68
67
  * Add configuration for compact vs expanded advisories reporting
69
68
 
70
69
  ## Contributing
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "bundler/gem_tasks"
2
4
  require "rake/testtask"
3
5
 
@@ -7,4 +9,4 @@ Rake::TestTask.new(:test) do |t|
7
9
  t.test_files = FileList["test/**/*_test.rb"]
8
10
  end
9
11
 
10
- task :default => :test
12
+ task default: :test
data/bin/console CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require "bundler/setup"
4
5
  require "pronto/bundler_audit"
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pronto
4
+ class BundlerAudit
5
+ module AdvisoryFormatters
6
+ # Pronto::BundlerAudit::AdvisoryFormatters::BaseAdvisoryFormatter is an
7
+ # abstract base class for formatting Bundler::Audit::Advisory objects
8
+ # as a String in the context of the given `gem`
9
+ # (Bundler::LazySpecification).
10
+ class BaseAdvisoryFormatter
11
+ # param gem [Bundler::LazySpecification]
12
+ # param advisory [Bundler::Audit::Advisory]
13
+ def initialize(gem:, advisory:)
14
+ @gem = gem
15
+ @advisory = advisory
16
+ end
17
+
18
+ def to_s
19
+ raise NotImplementedError
20
+ end
21
+
22
+ private
23
+
24
+ def gem_name
25
+ @gem.name
26
+ end
27
+
28
+ def gem_version
29
+ @gem.version
30
+ end
31
+
32
+ def advisory_description
33
+ if @advisory.cve
34
+ "CVE-#{@advisory.cve}"
35
+ elsif @advisory.osvdb
36
+ @advisory.osvdb
37
+ end
38
+ end
39
+
40
+ def advisory_criticality
41
+ str = @advisory.criticality.to_s.capitalize
42
+ str = "Unknown" if str.empty?
43
+ str
44
+ end
45
+
46
+ def advisory_url
47
+ @advisory.url
48
+ end
49
+
50
+ def advisory_title
51
+ @advisory.title
52
+ end
53
+
54
+ def advisory_solution
55
+ if any_patched_versions?
56
+ "Upgrade to #{patched_versions}."
57
+ else
58
+ "Remove or disable this gem until a patch is available!"
59
+ end
60
+ end
61
+
62
+ def patched_versions
63
+ @advisory.patched_versions.join(", ")
64
+ end
65
+
66
+ def any_patched_versions?
67
+ !@advisory.patched_versions.empty?
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base_advisory_formatter"
4
+
5
+ module Pronto
6
+ class BundlerAudit
7
+ module AdvisoryFormatters
8
+ # Pronto::BundlerAudit::AdvisoryFormatters::Compact is a compact message
9
+ # formatter for the given gem object and Bundler::Audit::Advisory#advisory
10
+ # object.
11
+ class Compact < BaseAdvisoryFormatter
12
+ def to_s
13
+ [
14
+ "Gem: #{gem_name} v#{gem_version}",
15
+ "#{advisory_criticality} Advisory: #{advisory_title} -- "\
16
+ "#{advisory_description} (#{advisory_url})",
17
+ "Solution: #{advisory_solution}"
18
+ ].join(" | ")
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base_advisory_formatter"
4
+
5
+ module Pronto
6
+ class BundlerAudit
7
+ module AdvisoryFormatters
8
+ # Pronto::BundlerAudit::AdvisoryFormatters::Verbose is a verbose message
9
+ # formatter for the given gem object and Bundler::Audit::Advisory#advisory
10
+ # object.
11
+ class Verbose < BaseAdvisoryFormatter
12
+ def to_s
13
+ [
14
+ "Name: #{gem_name}",
15
+ "Version: #{gem_version}",
16
+ "Advisory: #{advisory_description}",
17
+ "Criticality: #{advisory_criticality}",
18
+ "URL: #{advisory_url}",
19
+ "Title: #{advisory_title}",
20
+ "Solution: #{advisory_solution}"
21
+ ].join("\n")
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pronto/bundler_audit/scanner"
4
+
5
+ module Pronto
6
+ class BundlerAudit
7
+ # Pronto::BundlerAudit::Auditor:
8
+ # 1. updates the local ruby security database, and then
9
+ # 2. runs {Pronto::BundlerAudit::Scanner#call} on the given `patch`.
10
+ class Auditor
11
+ def initialize(patch)
12
+ @patch = patch
13
+ end
14
+
15
+ # @return (see: #run_scan)
16
+ def call
17
+ update_ruby_advisory_db
18
+ run_scanner
19
+ end
20
+
21
+ private
22
+
23
+ def update_ruby_advisory_db
24
+ Bundler::Audit::Database.update!(quiet: true)
25
+ end
26
+
27
+ # @return [Array>] if no advisories were found
28
+ # @return [Array<Pronto::Message>] if advisories were found
29
+ def run_scanner
30
+ scanner = Scanner.new(@patch)
31
+ scanner.call
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pronto
4
+ class BundlerAudit
5
+ module Results
6
+ # Pronto::BundlerAudit::Results::BaseResult is an abstract base class for
7
+ # the various Bundler::Audit::Scanner::* issue types.
8
+ class BaseResult
9
+ def initialize(scan_result)
10
+ @scan_result = scan_result
11
+ @gem = scan_result.gem
12
+ @advisory = scan_result.advisory
13
+ end
14
+
15
+ def call
16
+ report_result
17
+ end
18
+
19
+ private
20
+
21
+ def report_result
22
+ raise NotImplementedError
23
+ end
24
+
25
+ def build_message(message, level:, line:)
26
+ Message.new(
27
+ GEMFILE_LOCK_FILENAME,
28
+ line,
29
+ level,
30
+ message,
31
+ nil,
32
+ Pronto::BundlerAudit)
33
+ end
34
+
35
+ def message
36
+ raise NotImplementedError
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base_result"
4
+
5
+ module Pronto
6
+ class BundlerAudit
7
+ module Results
8
+ # Pronto::BundlerAudit::Results::InsecureSource builds a Pronto::Message
9
+ # for Bundler::Audit::Scanner::InsecureSource issues.
10
+ class InsecureSource < BaseResult
11
+ private
12
+
13
+ def report_result
14
+ build_message(
15
+ message,
16
+ line: nil,
17
+ level: :warning)
18
+ end
19
+
20
+ def message
21
+ "Insecure Source URI found: #{@scan_result.source}"
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base_result"
4
+ require "pronto/bundler_audit/advisory_formatters/verbose"
5
+ require "pronto/bundler_audit/advisory_formatters/compact"
6
+
7
+ module Pronto
8
+ class BundlerAudit
9
+ module Results
10
+ # Pronto::BundlerAudit::Results::UnpatchedGem builds a Pronto::Message for
11
+ # Bundler::Audit::Scanner::UnpatchedGem issues.
12
+ class UnpatchedGem < BaseResult
13
+ def initialize(scan_result, patch:)
14
+ super(scan_result)
15
+ @patch = patch
16
+ end
17
+
18
+ private
19
+
20
+ def report_result
21
+ build_message(
22
+ message,
23
+ level: :error,
24
+ line: find_relevant_line)
25
+ end
26
+
27
+ # @return [Pronto::Git::Line]
28
+ def find_relevant_line
29
+ first_added_line_for_affected_gem_name(@gem.name)
30
+ end
31
+
32
+ # @return [Pronto::Git::Line]
33
+ def first_added_line_for_affected_gem_name(gem_name)
34
+ @patch.added_lines.detect { |line| line.content.include?(gem_name) }
35
+ end
36
+
37
+ def message
38
+ advisory_formatter.to_s
39
+ end
40
+
41
+ def advisory_formatter
42
+ # TODO: Switch type based on configuration options, once available.
43
+ AdvisoryFormatters::Verbose.new(gem: @gem, advisory: @advisory)
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "results/insecure_source"
4
+ require_relative "results/unpatched_gem"
5
+
6
+ module Pronto
7
+ class BundlerAudit
8
+ # Pronto::BundlerAudit::Scanner runs runs Bundler::Audit::Scanner#scan on
9
+ # the given patch and then calls a {Pronto::BundlerAudit::BaseResult} based
10
+ # for each scan result.
11
+ class Scanner
12
+ def initialize(patch)
13
+ @patch = patch
14
+ end
15
+
16
+ # @return [Array>] if no advisories were found
17
+ # @return [Array<Pronto::Message>] if advisories were found)
18
+ def call
19
+ run_scan
20
+ end
21
+
22
+ private
23
+
24
+ def run_scan
25
+ run_scanner.map do |scan_result|
26
+ match_result(scan_result).call
27
+ end
28
+ end
29
+
30
+ def run_scanner
31
+ Bundler::Audit::Scanner.new.scan
32
+ end
33
+
34
+ def match_result(scan_result)
35
+ case scan_result
36
+ when Bundler::Audit::Scanner::InsecureSource
37
+ Results::InsecureSource.new(scan_result, patch: @patch)
38
+ when Bundler::Audit::Scanner::UnpatchedGem
39
+ Results::UnpatchedGem.new(scan_result, patch: @patch)
40
+ else
41
+ raise ArgumentError, "Unexpected type: #{scan_result.class}"
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Pronto
2
4
  # Pronto::BundlerAuditVersion
3
5
  module BundlerAuditVersion
4
- VERSION = "0.2.1"
6
+ VERSION = "0.3.0"
5
7
  end
6
8
  end
@@ -1,8 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "pronto"
2
4
  require "bundler/audit/database"
3
5
  require "bundler/audit/scanner"
4
- require "pronto/bundler_audit/version"
5
- require "pronto/bundler_audit/patch_handler"
6
6
 
7
7
  module Pronto
8
8
  # Pronto::BundlerAudit is a Pronto::Runner that:
@@ -12,13 +12,13 @@ module Pronto
12
12
  # 3. Runs bundle-audit to scan the Gemfile.lock
13
13
  # 4. Returns an Array of Pronto::Message objects if any advisories are found
14
14
  class BundlerAudit < Runner
15
- GEMFILE_LOCK_FILENAME = "Gemfile.lock".freeze
15
+ GEMFILE_LOCK_FILENAME = "Gemfile.lock"
16
16
 
17
17
  # @return [Array] per Pronto expectation
18
18
  def run
19
19
  if (patch = find_relevant_patch)
20
- patch_handler = PatchHandler.new(patch, runner: self)
21
- patch_handler.call
20
+ auditor = Auditor.new(patch)
21
+ auditor.call
22
22
  else
23
23
  []
24
24
  end
@@ -38,3 +38,6 @@ module Pronto
38
38
  end
39
39
  end
40
40
  end
41
+
42
+ require "pronto/bundler_audit/version"
43
+ require "pronto/bundler_audit/auditor"
@@ -1,4 +1,6 @@
1
- lib = File.expand_path("../lib", __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path("lib", __dir__)
2
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
5
  require "pronto/bundler_audit/version"
4
6
 
@@ -8,40 +10,31 @@ Gem::Specification.new do |spec|
8
10
  spec.authors = ["Paul Dobbins"]
9
11
  spec.email = ["paul.dobbins@icloud.com"]
10
12
 
11
- spec.summary = %q{Pronto runner for bundler-audit, patch-level verification for bundler.}
13
+ spec.summary =
14
+ "Pronto runner for bundler-audit, patch-level verification for bundler."
12
15
  spec.homepage = "http://github.com/pdobb/pronto-bundler_audit"
13
16
  spec.license = "MIT"
14
17
 
15
- # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
16
- # to allow pushing to a single host or delete this section to allow pushing to any host.
17
- # if spec.respond_to?(:metadata)
18
- # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
19
-
20
- # spec.metadata["homepage_uri"] = spec.homepage
21
- # spec.metadata["source_code_uri"] = "https://github.com/pdobb/pronto-bundler_audit"
22
- # spec.metadata["changelog_uri"] = "https://github.com/pdobb/pronto-bundler_audit/blob/master/CHANGELOG.md"
23
- # else
24
- # raise "RubyGems 2.0 or newer is required to protect against " \
25
- # "public gem pushes."
26
- # end
27
-
28
18
  # Specify which files should be added to the gem when it is released.
29
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
30
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
31
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
+ # The `git ls-files -z` loads the files in the RubyGem that have been added
20
+ # into git.
21
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
22
+ `git ls-files -z`.split("\x0").reject { |f|
23
+ f.match(%r{^(test|spec|features)/})
24
+ }
32
25
  end
33
26
  spec.bindir = "exe"
34
27
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
35
28
  spec.require_paths = ["lib"]
36
29
 
37
- spec.add_runtime_dependency "pronto", "~> 0"
38
30
  spec.add_runtime_dependency "bundler-audit", "~> 0"
31
+ spec.add_runtime_dependency "pronto", "~> 0"
39
32
 
40
33
  spec.add_development_dependency "bundler", "~> 2"
41
34
  spec.add_development_dependency "byebug", "~> 11"
42
35
  spec.add_development_dependency "minitest", "~> 5"
43
36
  spec.add_development_dependency "minitest-reporters", "~> 1"
44
- spec.add_development_dependency "mocha", "~> 1"
37
+ spec.add_development_dependency "much-stub", "~> 0"
45
38
  spec.add_development_dependency "pry", "~> 0"
46
39
  spec.add_development_dependency "pry-byebug", "~> 3"
47
40
  spec.add_development_dependency "rake", "~> 12"
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pronto-bundler_audit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Dobbins
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-04-30 00:00:00.000000000 Z
11
+ date: 2019-05-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: pronto
14
+ name: bundler-audit
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
@@ -25,7 +25,7 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: bundler-audit
28
+ name: pronto
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
@@ -95,19 +95,19 @@ dependencies:
95
95
  - !ruby/object:Gem::Version
96
96
  version: '1'
97
97
  - !ruby/object:Gem::Dependency
98
- name: mocha
98
+ name: much-stub
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '1'
103
+ version: '0'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '1'
110
+ version: '0'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: pry
113
113
  requirement: !ruby/object:Gem::Requirement
@@ -192,6 +192,8 @@ extensions: []
192
192
  extra_rdoc_files: []
193
193
  files:
194
194
  - ".gitignore"
195
+ - ".rubocop"
196
+ - ".rubocop.yml"
195
197
  - ".travis.yml"
196
198
  - CHANGELOG.md
197
199
  - Gemfile
@@ -204,7 +206,14 @@ files:
204
206
  - images/github-check.png
205
207
  - images/github-comment.png
206
208
  - lib/pronto/bundler_audit.rb
207
- - lib/pronto/bundler_audit/patch_handler.rb
209
+ - lib/pronto/bundler_audit/advisory_formatters/base_advisory_formatter.rb
210
+ - lib/pronto/bundler_audit/advisory_formatters/compact.rb
211
+ - lib/pronto/bundler_audit/advisory_formatters/verbose.rb
212
+ - lib/pronto/bundler_audit/auditor.rb
213
+ - lib/pronto/bundler_audit/results/base_result.rb
214
+ - lib/pronto/bundler_audit/results/insecure_source.rb
215
+ - lib/pronto/bundler_audit/results/unpatched_gem.rb
216
+ - lib/pronto/bundler_audit/scanner.rb
208
217
  - lib/pronto/bundler_audit/version.rb
209
218
  - pronto-bundler_audit.gemspec
210
219
  homepage: http://github.com/pdobb/pronto-bundler_audit
@@ -1,165 +0,0 @@
1
- module Pronto
2
- class BundlerAudit < Runner
3
- # Pronto::BundlerAudit::PatchHandler runs Bundle Audit on the given patch
4
- # and returns an Array of Pronto::Message objects if any advisories are
5
- # found.
6
- class PatchHandler
7
- def initialize(patch, runner:)
8
- @patch = patch
9
- @runner = runner
10
- end
11
-
12
- # @return (see: #run_scan)
13
- def call
14
- update_ruby_advisory_db
15
- run_scan
16
- end
17
-
18
- private
19
-
20
- def update_ruby_advisory_db
21
- Bundler::Audit::Database.update!(quiet: true)
22
- end
23
-
24
- # @return [Array>] if no advisories were found
25
- # @return [Array<Pronto::Message>] if advisories were found
26
- def run_scan
27
- scanner = Bundler::Audit::Scanner.new
28
-
29
- scanner.scan.inject([]) do |acc, scan_result|
30
- acc << process_scan_result(scan_result)
31
- end
32
- end
33
-
34
- def process_scan_result(scan_result)
35
- case scan_result
36
- when Bundler::Audit::Scanner::InsecureSource
37
- report_insecure_source_scan_result
38
- when Bundler::Audit::Scanner::UnpatchedGem
39
- report_unpatched_gem_scan_result(scan_result)
40
- else
41
- raise ArgumentError, "unexpected type: #{scan_result.class}"
42
- end
43
- end
44
-
45
- def report_insecure_source_scan_result(scan_result)
46
- build_warning_message(
47
- "Insecure Source URI found: #{scan_result.source}")
48
- end
49
-
50
- def report_unpatched_gem_scan_result(scan_result)
51
- advisory =
52
- AdvisoryFormatter.new(
53
- gem: scan_result.gem, advisory: scan_result.advisory)
54
- message = advisory.to_compact_s
55
- line = find_relevant_line(advisory)
56
-
57
- build_error_message(message, line: line)
58
- end
59
-
60
- # @return [Pronto::Git::Line]
61
- def find_relevant_line(advisory)
62
- first_added_line_for_affected_gem_name(advisory.gem_name)
63
- end
64
-
65
- # @return [Pronto::Git::Line]
66
- def first_added_line_for_affected_gem_name(gem_name)
67
- @patch.added_lines.detect { |line| line.content.include?(gem_name) }
68
- end
69
-
70
- def build_warning_message(message)
71
- build_message(message, level: :warning)
72
- end
73
-
74
- def build_error_message(message, line:)
75
- build_message(message, level: :error, line: line)
76
- end
77
-
78
- def build_message(message, level:, line:)
79
- Message.new(
80
- GEMFILE_LOCK_FILENAME, line, level, message, nil, @runner.class)
81
- end
82
-
83
- # Pronto::BundlerAudit::PatchHandler::AdvisoryFormatter is a message
84
- # formatter for the given gem object and Bundler::Audit::Advisory#advisory
85
- # object.
86
- class AdvisoryFormatter
87
- # param gem [Bundler::LazySpecification]
88
- # param advisory [Bundler::Audit::Advisory]
89
- def initialize(gem:, advisory:)
90
- @gem = gem
91
- @advisory = advisory
92
- end
93
-
94
- def to_s
95
- [
96
- "Name: #{gem_name}",
97
- "Version: #{gem_version}",
98
- "Advisory: #{advisory_description}",
99
- "Criticality: #{advisory_criticality}",
100
- "URL: #{advisory_url}",
101
- "Title: #{advisory_title}",
102
- "Solution: #{advisory_solution}"
103
- ].join("\n")
104
- end
105
-
106
- def to_compact_s
107
- [
108
- "Gem: #{gem_name} v#{gem_version}",
109
- "#{advisory_criticality} Advisory: #{advisory_title} -- "\
110
- "#{advisory_description} (#{advisory_url})",
111
- "Solution: #{advisory_solution}"
112
- ].join(" | ")
113
- end
114
-
115
- def gem_name
116
- @gem.name
117
- end
118
-
119
- private
120
-
121
- def gem_version
122
- @gem.version
123
- end
124
-
125
- def advisory_description
126
- if @advisory.cve
127
- "CVE-#{@advisory.cve}"
128
- elsif @advisory.osvdb
129
- @advisory.osvdb
130
- end
131
- end
132
-
133
- def advisory_criticality
134
- str = @advisory.criticality.to_s.capitalize
135
- str = "Unknown" if str.empty?
136
- str
137
- end
138
-
139
- def advisory_url
140
- @advisory.url
141
- end
142
-
143
- def advisory_title
144
- @advisory.title
145
- end
146
-
147
- def advisory_solution
148
- if any_patched_versions?
149
- "Upgrade to #{patched_versions}."
150
- else
151
- "Remove or disable this gem until a patch is available!"
152
- end
153
- end
154
-
155
- def patched_versions
156
- @advisory.patched_versions.join(', ')
157
- end
158
-
159
- def any_patched_versions?
160
- !@advisory.patched_versions.empty?
161
- end
162
- end
163
- end
164
- end
165
- end