pronto-bundler_audit 0.3.0 → 0.7.0

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: 2a6328fffd859750def2c69f570ea970ecc44aa1b31362dfa03b5933cde49201
4
- data.tar.gz: c6c226e11867996c7d19d53089a31e20b87acaebe3593713f11d310f7e1b602b
3
+ metadata.gz: 8112a836fbdf9cfbedc584f8a6f6546da622fea402df4be5e6a21b883504377e
4
+ data.tar.gz: 1e2c2c4e8144bc9c1dbc8d2c84887a0419d95570e357b92054ff73400517c095
5
5
  SHA512:
6
- metadata.gz: df67a7343d90292e9b15fdfeb6c75eab64b76b27a98ee1feffb3ac9b2c1ef3f0e20822048a595018904d19655c8c82142635644409e01faaee3fa313fccc5826
7
- data.tar.gz: 167db3c4bfbd04bec6b25d519f0fd060809de610f899d8e3cc166601baac28ffcc512129ab02496305899df4b7f192fc77a274352f4cc2fcdfcb8f6c846e5edb
6
+ metadata.gz: c92d25f870b348a78b3f52f16d4fd839b14c4f96a10ad59f803a27a4891160c6249ed397a7d28ce52068bf01be4c609f85a8e106710c97ab9fd10aa096455c4d
7
+ data.tar.gz: 9e12deff351a41433d0386567c46e3240a06ca71ccc7eb588ff15b95916be62221678705255619b906f1c7272c4e54f832cad10a1d7e9eb44903ded29fe885c1
data/.rubocop.yml CHANGED
@@ -129,6 +129,9 @@ Style/FormatString:
129
129
  Style/Lambda:
130
130
  EnforcedStyle: literal
131
131
 
132
+ Style/LambdaCall:
133
+ Enabled: false # Allow ServiceObject.(*). Only use on classes, not instances.
134
+
132
135
  Style/NumericPredicate:
133
136
  Enabled: false # Trying to be welcoming to earlier versions of Ruby.
134
137
  # AutoCorrect: true
data/.travis.yml CHANGED
@@ -4,14 +4,13 @@ env:
4
4
  sudo: false
5
5
  language: ruby
6
6
  rvm:
7
- - 2.3
8
7
  - 2.4
9
8
  - 2.5
10
9
  - 2.6
11
10
  - ruby-head
12
11
  notifications:
13
12
  email: false
14
- before_install: gem install bundler -v 2.0.1
13
+ before_install: gem install bundler -v 2.0.2 --no-document
15
14
  cache: bundler
16
15
  before_script:
17
16
  - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
data/CHANGELOG.md CHANGED
@@ -1,3 +1,33 @@
1
+ ### 0.7.0 - 2021-04-29
2
+ - [#11](https://github.com/pdobb/pronto-bundler_audit/pull/11)
3
+ - Attempted Fix for `NoMethodError: undefined method 'line' for #<Pronto::BundlerAudit::Results::ProntoMessagesAdapter::DeepLine...>`
4
+ - [#10](https://github.com/pdobb/pronto-bundler_audit/pull/10) Pronto 0.11.0 compatibility
5
+ - Fix Pronto -> GitHub call :publish_pull_request_comments instead of :create_pull_request_review
6
+
7
+ #### NOTE:
8
+ This version requires pronto 0.11+ and bundler-audit 0.8+. Use v0.6.0 if you cannot update pronto and bundler-audit at this time.
9
+
10
+ ### 0.6.1 - 2021-04-08
11
+ - Unreleased... see 0.7.0 instead.
12
+
13
+ ### 0.6.0 - 2019-11-30
14
+ - [#7](https://github.com/pdobb/pronto-bundler_audit/pull/7) Add configurability via .pronto-bundler_audit.yml file
15
+ - For now, the only configuration available is ignoring advisories in the bundler_audit scan. See the [README](https://github.com/pdobb/pronto-bundler_audit#configuration).
16
+
17
+ ### 0.5.1 - 2019-10-24
18
+ - Fix Pronto -> GitHub reporting errors
19
+ - If Gemfile.lock is not in the PR then Pronto would fail when attempting to create a comment on the Gemfile.lock file withing the PR.
20
+ - Note: This issue isn't fully fixed yet, but at least doesn't fail flat out.
21
+ - To fully fix: would like to still add a PR-level comment with CVE issue(s) instead of requiring the user to dig into their CI output to see the CVE issue(s).
22
+
23
+ ### 0.5.0 - 2019-07-31
24
+ - Fix Pronto -> GitHub reporting errors
25
+ - Thanks to Inestor for the [bug report](https://github.com/pdobb/pronto-bundler_audit/issues/2).
26
+ - Credit for the approach taken here goes to to os6sense and [his hard work](https://github.com/pdobb/pronto-bundler_audit/pull/4/files)
27
+
28
+ ### 0.4.0 - 2019-05-08
29
+ - Remove patch-level processing... just always scan Gemfile.lock when this runner is invoked.
30
+
1
31
  ### 0.3.0 - 2019-05-03
2
32
  - Internal rewrite into smaller objects with full test coverage
3
33
  - Switch to using the verbose advisory formatter by default
@@ -13,6 +43,5 @@
13
43
  - Add line number to Pronto::Message; fixes GitHub API usage error when attempting to add errors to PR comments
14
44
  - Add gem version requirements to gemspec
15
45
 
16
-
17
46
  ### 0.1.0 - 2019-04-28
18
47
  - Initial release!
data/Gemfile.lock CHANGED
@@ -1,89 +1,100 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pronto-bundler_audit (0.3.0)
5
- bundler-audit (~> 0)
6
- pronto (~> 0)
4
+ pronto-bundler_audit (0.7.0)
5
+ bundler-audit (~> 0.8)
6
+ pronto (~> 0.11)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- addressable (2.6.0)
12
- public_suffix (>= 2.0.2, < 4.0)
11
+ addressable (2.7.0)
12
+ public_suffix (>= 2.0.2, < 5.0)
13
13
  ansi (1.5.0)
14
14
  ast (2.4.0)
15
15
  builder (3.2.3)
16
- bundler-audit (0.6.1)
16
+ bundler-audit (0.8.0)
17
17
  bundler (>= 1.2.0, < 3)
18
- thor (~> 0.18)
18
+ thor (~> 1.0)
19
19
  byebug (11.0.1)
20
20
  coderay (1.1.2)
21
- docile (1.3.1)
22
- faraday (0.15.4)
21
+ docile (1.3.2)
22
+ faraday (1.4.1)
23
+ faraday-excon (~> 1.1)
24
+ faraday-net_http (~> 1.0)
25
+ faraday-net_http_persistent (~> 1.1)
23
26
  multipart-post (>= 1.2, < 3)
24
- gitlab (4.11.0)
25
- httparty (~> 0.14, >= 0.14.0)
27
+ ruby2_keywords (>= 0.0.4)
28
+ faraday-excon (1.1.0)
29
+ faraday-net_http (1.0.1)
30
+ faraday-net_http_persistent (1.1.0)
31
+ gitlab (4.17.0)
32
+ httparty (~> 0.18)
26
33
  terminal-table (~> 1.5, >= 1.5.1)
27
- httparty (0.17.0)
34
+ httparty (0.18.1)
28
35
  mime-types (~> 3.0)
29
36
  multi_xml (>= 0.5.2)
30
- jaro_winkler (1.5.2)
31
- json (2.2.0)
37
+ jaro_winkler (1.5.3)
38
+ json (2.3.1)
32
39
  method_source (0.9.2)
33
- mime-types (3.2.2)
40
+ mime-types (3.3.1)
34
41
  mime-types-data (~> 3.2015)
35
- mime-types-data (3.2019.0331)
42
+ mime-types-data (3.2021.0225)
36
43
  minitest (5.11.3)
37
44
  minitest-reporters (1.3.6)
38
45
  ansi
39
46
  builder
40
47
  minitest (>= 5.0)
41
48
  ruby-progressbar
42
- much-stub (0.1.0)
49
+ much-stub (0.1.1)
43
50
  multi_xml (0.6.0)
44
- multipart-post (2.0.0)
45
- octokit (4.14.0)
51
+ multipart-post (2.1.1)
52
+ octokit (4.21.0)
53
+ faraday (>= 0.9)
46
54
  sawyer (~> 0.8.0, >= 0.5.3)
47
55
  parallel (1.17.0)
48
56
  parser (2.6.3.0)
49
57
  ast (~> 2.4.0)
50
- pronto (0.10.0)
51
- gitlab (~> 4.0, >= 4.0.0)
58
+ pronto (0.11.0)
59
+ gitlab (~> 4.4, >= 4.4.0)
52
60
  httparty (>= 0.13.7)
53
61
  octokit (~> 4.7, >= 4.7.0)
54
62
  rainbow (>= 2.2, < 4.0)
55
- rugged (~> 0.24, >= 0.23.0)
56
- thor (~> 0.20.0)
63
+ rexml (~> 3.2)
64
+ rugged (>= 0.23.0, < 1.1.0)
65
+ thor (>= 0.20.3, < 2.0)
57
66
  pry (0.12.2)
58
67
  coderay (~> 1.1.0)
59
68
  method_source (~> 0.9.0)
60
69
  pry-byebug (3.7.0)
61
70
  byebug (~> 11.0)
62
71
  pry (~> 0.10)
63
- public_suffix (3.0.3)
72
+ public_suffix (4.0.6)
64
73
  rainbow (3.0.0)
65
- rake (12.3.2)
66
- rubocop (0.68.1)
74
+ rake (12.3.3)
75
+ rexml (3.2.5)
76
+ rubocop (0.73.0)
67
77
  jaro_winkler (~> 1.5.1)
68
78
  parallel (~> 1.10)
69
- parser (>= 2.5, != 2.5.1.1)
79
+ parser (>= 2.6)
70
80
  rainbow (>= 2.2.2, < 4.0)
71
81
  ruby-progressbar (~> 1.7)
72
- unicode-display_width (>= 1.4.0, < 1.6)
73
- ruby-progressbar (1.10.0)
74
- rugged (0.28.1)
82
+ unicode-display_width (>= 1.4.0, < 1.7)
83
+ ruby-progressbar (1.10.1)
84
+ ruby2_keywords (0.0.4)
85
+ rugged (1.0.1)
75
86
  sawyer (0.8.2)
76
87
  addressable (>= 2.3.5)
77
88
  faraday (> 0.8, < 2.0)
78
- simplecov (0.16.1)
89
+ simplecov (0.17.0)
79
90
  docile (~> 1.1)
80
91
  json (>= 1.8, < 3)
81
92
  simplecov-html (~> 0.10.0)
82
93
  simplecov-html (0.10.2)
83
94
  terminal-table (1.8.0)
84
95
  unicode-display_width (~> 1.1, >= 1.1.1)
85
- thor (0.20.3)
86
- unicode-display_width (1.5.0)
96
+ thor (1.1.0)
97
+ unicode-display_width (1.6.0)
87
98
 
88
99
  PLATFORMS
89
100
  ruby
@@ -102,4 +113,4 @@ DEPENDENCIES
102
113
  simplecov (~> 0.16)
103
114
 
104
115
  BUNDLED WITH
105
- 2.0.1
116
+ 2.2.16
data/README.md CHANGED
@@ -1,3 +1,8 @@
1
+ # Maintainer needed
2
+
3
+ Unfortunately, I (@pdobb) am no longer working on any projects and, therefore, don't have a good way to test fixes. There are probably numerous fixes needed right now as pronto 0.11.0 has been recently released and since there is no proper API for using pronto's internals, each update to pronto will likely mean breaking changes in gems such as this one. But, probably... especially this one. This gem attempts to do something that pronto isn't made for: examine code from a file that isn't necessarily contained within the diff that pronto is analyzing. Most of pronto-bundler_audit is attempting to solve this problem by overriding the pronto API with custom adapter objects standing in for Pronto-native object.
4
+
5
+
1
6
  [![Gem Version](https://badge.fury.io/rb/pronto-bundler_audit.svg)](https://badge.fury.io/rb/pronto-bundler_audit)
2
7
  [![Build Status](https://travis-ci.org/pdobb/pronto-bundler_audit.svg?branch=master)](https://travis-ci.org/pdobb/pronto-bundler_audit)
3
8
  [![Maintainability](https://api.codeclimate.com/v1/badges/7ac01a6a6eace46487d9/maintainability)](https://codeclimate.com/github/pdobb/pronto-bundler_audit/maintainability)
@@ -26,35 +31,83 @@ Or install it yourself as:
26
31
  ## Compatibility
27
32
 
28
33
  Tested MRI Ruby Versions:
29
- * 2.3
30
34
  * 2.4
31
35
  * 2.5
32
36
  * 2.6
33
37
  * edge
34
38
 
39
+ NOTE: pronto-bundler_audit v0.7.0 requires pronto v0.11+ and bundler-audit v0.8+. Use pronto-bundler_audit v0.6.0 if you cannot update pronto and bundler-audit at this time.
40
+
35
41
  ## Usage
36
42
 
37
- Once installed as a gem, this runner activate automatically when [running Pronto](https://github.com/prontolabs/pronto#usage) -- no configuration is required.
43
+ Once installed as a gem, this runner activates automatically when [running Pronto](https://github.com/prontolabs/pronto#usage) -- no configuration is required.
38
44
 
39
- ### Examples
45
+ Note: Unlike most Pronto runners, pronto-bundler_audit will always scan Gemfile.lock whenever Pronto is run. That is, this runner does not only run against patches/diffs made on Gemfile.lock. The point is to find issues/advisories on every Pronto run, not just when Gemfile.lock has been updated. Because, otherwise, this gem wouldn't really help us find vulnerabilities in a project's gems in a timely fashion.
40
46
 
41
- #### Local Pronto Run
47
+ ## Configuration
48
+
49
+ Configuration of the pronto-bundler_audit gem is available by creating a YAML file on the project root, called `.pronto-bundler_audit.yml`.
50
+
51
+ Available configuration options include:
52
+
53
+ ```yaml
54
+ Advisories:
55
+ # Send the following advisory names to bundler_audit's `ignored` option.
56
+ Ignore:
57
+ - CVE-YYYY-####1
58
+ - CVE-YYYY-####2
59
+ ```
60
+
61
+ The above acts the same as running `bundle-audit check --ignore CVE-YYYY-####1 CVE-YYYY-####2`.
62
+
63
+
64
+ ## Examples
65
+
66
+ ### Local Pronto Run
67
+
68
+ #### Compact Mode
42
69
 
43
70
  ```bash
44
- $ time pronto run -c=development --runner bundler_audit
71
+ $ pronto run -c=master --runner bundler_audit
45
72
  Running Pronto::BundlerAudit
46
73
  Gemfile.lock: E: Gem: bootstrap-sass v3.4.0 | Medium Advisory: XSS vulnerability in bootstrap-sass -- CVE-2019-8331 (https://blog.getbootstrap.com/2019/02/13/bootstrap-4-3-1-and-3-4-1/) | Solution: Upgrade to >= 3.4.1.
74
+ ```
75
+
76
+ #### Verbose Mode
47
77
 
48
- real 0m1.417s
49
- user 0m0.773s
50
- sys 0m0.252s
78
+ ```bash
79
+ $ pronto run -c=master --runner bundler_audit
80
+ Running Pronto::BundlerAudit
81
+ Gemfile.lock: E: Name: bootstrap-sass
82
+ Version: 3.4.0
83
+ Advisory: CVE-2019-8331
84
+ Criticality: Medium
85
+ URL: https://blog.getbootstrap.com/2019/02/13/bootstrap-4-3-1-and-3-4-1/
86
+ Title: XSS vulnerability in bootstrap-sass
87
+ Solution: Upgrade to >= 3.4.1.
51
88
  ```
52
89
 
90
+ #### Continuous Integration Output
91
+
92
+ ![CI Output](images/ci-output.png)
93
+
94
+
53
95
  #### Github Pull Request - Checks
96
+
54
97
  ![Github Check](images/github-check.png)
55
98
 
56
99
  #### Github Pull Request - Comments
57
- ![Github Comment](images/github-comment.png)
100
+
101
+ #### Verbose Mode
102
+
103
+ ![Github Comment - Verbose](images/github-comment-verbose.png)
104
+
105
+ #### Compact Mode
106
+
107
+ Note: Not yet available by configuration.
108
+
109
+ ![Github Comment - Compact](images/github-comment-compact.png)
110
+
58
111
 
59
112
  ## Development
60
113
 
@@ -62,6 +115,11 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
62
115
 
63
116
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
64
117
 
118
+ ### Testing
119
+
120
+ GitHub integration testing isn't easy. I have created a test app for myself at: https://github.com/pdobb/pronto-bundler_audit_test_app.
121
+
122
+
65
123
  ## TODO
66
124
 
67
125
  * Add configuration for compact vs expanded advisories reporting
Binary file
Binary file
@@ -0,0 +1,36 @@
1
+ module Pronto
2
+ module Formatter
3
+ # Pronto::Formatter::GithubPullRequestReviewFormatter comes from the
4
+ # Pronto gem itself.
5
+ #
6
+ # # Note: Ignore `method redefined` warnings on these methods.
7
+ #
8
+ # The methods below are feature overrides to:
9
+ # 1. prevent the {#line_number} class from failing if none of the patches
10
+ # contain the `message.line.new_lineno` value found. Which can happen
11
+ # in the context of this pronto-bundler audit gem since we aren't
12
+ # necessarily altering the Gemfile.lock file within a PR at the time of
13
+ # finding an issue in the Gemfile.lock file.
14
+ # 2. FIXME: Prevent a POST error due to an unknown file path in the
15
+ # traditional Pull Request Review comment style.
16
+ class GithubPullRequestReviewFormatter
17
+ def submit_comments(client, comments)
18
+ client.publish_pull_request_comments(comments)
19
+ rescue Octokit::UnprocessableEntity, HTTParty::Error => e
20
+ # If Gemfile.lock doesn't exist in the PR, then attempt a non-review
21
+ # style comment instead (which doesn't attempt to reference a file
22
+ # path and line number).
23
+ begin
24
+ comments.each { |comment| client.create_pull_comment(comment) }
25
+ rescue Octokit::UnprocessableEntity, HTTParty::Error => e
26
+ $stderr.puts "Failed to post: #{e.message}"
27
+ end
28
+ end
29
+
30
+ def line_number(message, patches)
31
+ line = patches.find_line(message.full_path, message.line.new_lineno)
32
+ line&.position || message.line.new_lineno
33
+ end
34
+ end
35
+ end
36
+ end
@@ -1,43 +1,54 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "pronto"
4
+
5
+ # Pronto gem overrides (use sparingly):
6
+ require "formatter/github_pull_request_review_formatter"
7
+
4
8
  require "bundler/audit/database"
5
9
  require "bundler/audit/scanner"
6
10
 
7
11
  module Pronto
8
- # Pronto::BundlerAudit is a Pronto::Runner that:
9
- # 1. Finds the most relevant patch (the last patch that contains a change to
10
- # Gemfile.lock)
11
- # 2. Updates the Ruby Advisory Database
12
- # 3. Runs bundle-audit to scan the Gemfile.lock
13
- # 4. Returns an Array of Pronto::Message objects if any advisories are found
14
- class BundlerAudit < Runner
12
+ # Pronto::BundlerAudit is a ::Pronto::Runner that:
13
+ # 1. Updates the Ruby Advisory Database,
14
+ # 2. Runs bundle-audit to scan the Gemfile.lock, and then
15
+ # 3. Returns an Array of ::Pronto::Message objects if any issues or advisories
16
+ # are found.
17
+ class BundlerAudit < ::Pronto::Runner
15
18
  GEMFILE_LOCK_FILENAME = "Gemfile.lock"
16
19
 
17
- # @return [Array] per Pronto expectation
20
+ def self.configuration
21
+ @configuration ||= Pronto::BundlerAudit::Configuration.new
22
+ end
23
+
24
+ # @return [Array<Pronto::Message>] one for each issue found
18
25
  def run
19
- if (patch = find_relevant_patch)
20
- auditor = Auditor.new(patch)
21
- auditor.call
22
- else
23
- []
24
- end
26
+ results = Auditor.call
27
+
28
+ Pronto::BundlerAudit::Results::ProntoMessagesAdapter.call(
29
+ results,
30
+ runner: self)
25
31
  end
26
32
 
27
- private
33
+ # @return [Pathname] the absolute path to the current git repo / code.
34
+ def path
35
+ Pathname.new(File.expand_path("."))
36
+ end
28
37
 
29
- def find_relevant_patch
30
- @patches.to_a.reverse.detect { |patch|
31
- patch.additions > 0 && relevant_patch_path?(patch)
32
- }
38
+ def filename
39
+ GEMFILE_LOCK_FILENAME
33
40
  end
34
41
 
35
- def relevant_patch_path?(patch)
36
- patch_path = patch.new_file_full_path.to_s
37
- patch_path.end_with?(GEMFILE_LOCK_FILENAME)
42
+ # Don't really need a commit SHA for Pronto's GitHubFormatter to work. Just
43
+ # need to return nil here, and in
44
+ # {Pronto::BundlerAudit::Results::ProntoMessagesAdapter::DeepLine#commit_sha}.
45
+ def commit_sha
46
+ nil
38
47
  end
39
48
  end
40
49
  end
41
50
 
51
+ require "pronto/bundler_audit/configuration"
42
52
  require "pronto/bundler_audit/version"
43
53
  require "pronto/bundler_audit/auditor"
54
+ require "pronto/bundler_audit/results/pronto_messages_adapter"
@@ -5,14 +5,14 @@ require "pronto/bundler_audit/scanner"
5
5
  module Pronto
6
6
  class BundlerAudit
7
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`.
8
+ # 1. Updates the local ruby security database, and then
9
+ # 2. Runs {::Pronto::BundlerAudit::Scanner#call}.
10
10
  class Auditor
11
- def initialize(patch)
12
- @patch = patch
11
+ def self.call(*args)
12
+ new(*args).call
13
13
  end
14
14
 
15
- # @return (see: #run_scan)
15
+ # @return (see: #run_scanner)
16
16
  def call
17
17
  update_ruby_advisory_db
18
18
  run_scanner
@@ -21,14 +21,14 @@ module Pronto
21
21
  private
22
22
 
23
23
  def update_ruby_advisory_db
24
- Bundler::Audit::Database.update!(quiet: true)
24
+ ::Bundler::Audit::Database.update!(quiet: true)
25
25
  end
26
26
 
27
- # @return [Array>] if no advisories were found
28
- # @return [Array<Pronto::Message>] if advisories were found
27
+ # @return [Array<>] if no issues were found
28
+ # @return [Array<Pronto::BundlerAudit::Results::BaseResult>] if unpatched
29
+ # gem sources or if advisories were found
29
30
  def run_scanner
30
- scanner = Scanner.new(@patch)
31
- scanner.call
31
+ Pronto::BundlerAudit::Scanner.call
32
32
  end
33
33
  end
34
34
  end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pronto
4
+ class BundlerAudit
5
+ # Pronto::BundlerAudit::Configuration loads configuration for the
6
+ # pronto-bundler_audit gem from the `.pronto-bundler_audit.yml` file and
7
+ # provides service methods for reading configuration settings.
8
+ class Configuration
9
+ def initialize(path: ".pronto-bundler_audit.yml")
10
+ @config_file_path = path
11
+ end
12
+
13
+ # @return [Array<Sring>] the Advisory Names for bundler_audit to ignore
14
+ def ignored_advisories
15
+ configuration.dig("Advisories", "Ignore")
16
+ end
17
+
18
+ private
19
+
20
+ def configuration
21
+ @configuration ||=
22
+ if File.exist?(@config_file_path)
23
+ YAML.load(configuration_file.read)
24
+ else
25
+ {}
26
+ end
27
+ end
28
+
29
+ def configuration_file
30
+ File.open(@config_file_path)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pronto
4
+ class BundlerAudit
5
+ module GemfileLock
6
+ # Pronto::BundlerAudit::GemfileLock::Scanner scans the given `path` for
7
+ # the given `gem_name` and returns an Integer representing the line number
8
+ # of the gem in the Gemfile.lock file.
9
+ class Scanner
10
+ def initialize(gem_name:, path: GEMFILE_LOCK_FILENAME)
11
+ unless File.exist?(path)
12
+ raise ArgumentError, "Gemfile.lock path not found"
13
+ end
14
+
15
+ @gem_name = gem_name
16
+ @path = path
17
+ end
18
+
19
+ def self.call(*args)
20
+ new(*args).call
21
+ end
22
+
23
+ def call
24
+ determine_relevant_line_number
25
+ end
26
+
27
+ private
28
+
29
+ # @return [Integer] the line number; or 0 if not found
30
+ def determine_relevant_line_number
31
+ line_number = 0
32
+
33
+ File.foreach(@path).with_index do |line, index|
34
+ next unless line.include?(@gem_name)
35
+
36
+ line_number = index.next
37
+ break
38
+ end
39
+
40
+ line_number
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -5,6 +5,10 @@ module Pronto
5
5
  module Results
6
6
  # Pronto::BundlerAudit::Results::BaseResult is an abstract base class for
7
7
  # the various Bundler::Audit::Scanner::* issue types.
8
+ #
9
+ # Note: These result objects act as a stand-in for ::Pronto::Message
10
+ # objects, which are later translated into actual ::Pronto::Message
11
+ # objects via {Pronto::BundlerAudit::MessagesAdapter}.
8
12
  class BaseResult
9
13
  def initialize(scan_result)
10
14
  @scan_result = scan_result
@@ -12,26 +16,17 @@ module Pronto
12
16
  @advisory = scan_result.advisory
13
17
  end
14
18
 
15
- def call
16
- report_result
17
- end
18
-
19
- private
20
-
21
- def report_result
19
+ # @return [Symbol]
20
+ def level
22
21
  raise NotImplementedError
23
22
  end
24
23
 
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)
24
+ # @return [Integer, NilClass]
25
+ def line
26
+ raise NotImplementedError
33
27
  end
34
28
 
29
+ # @return [String]
35
30
  def message
36
31
  raise NotImplementedError
37
32
  end
@@ -5,18 +5,21 @@ require_relative "base_result"
5
5
  module Pronto
6
6
  class BundlerAudit
7
7
  module Results
8
- # Pronto::BundlerAudit::Results::InsecureSource builds a Pronto::Message
9
- # for Bundler::Audit::Scanner::InsecureSource issues.
8
+ # Pronto::BundlerAudit::Results::InsecureSource is a stand-in for the
9
+ # ::Pronto::Message object for ::Bundler::Audit::Scanner::InsecureSource
10
+ # issues.
10
11
  class InsecureSource < BaseResult
11
- private
12
+ # @return [Symbol]
13
+ def level
14
+ :warning
15
+ end
12
16
 
13
- def report_result
14
- build_message(
15
- message,
16
- line: nil,
17
- level: :warning)
17
+ # @return [NilClass]
18
+ def line
19
+ nil
18
20
  end
19
21
 
22
+ # @return [String]
20
23
  def message
21
24
  "Insecure Source URI found: #{@scan_result.source}"
22
25
  end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pronto
4
+ class BundlerAudit
5
+ module Results
6
+ # Pronto::BundlerAudit::Results::ProntoMessagesAdapter is an adapter layer
7
+ # for converting {Pronto::BundlerAudit::BaseResult} objects into
8
+ # ::Pronto::Message objects for use by the Pronto gem when sending issue
9
+ # details to GitHub, etc.
10
+ class ProntoMessagesAdapter
11
+ def initialize(results, runner:)
12
+ @results = Array(results)
13
+ @runner = runner
14
+ end
15
+
16
+ def self.call(*args)
17
+ new(*args).call
18
+ end
19
+
20
+ def call
21
+ @results.map { |result|
22
+ ::Pronto::Message.new(
23
+ @runner.filename,
24
+ DeepLine.new(line_number: result.line, path: @runner.path),
25
+ result.level,
26
+ result.message,
27
+ @runner.commit_sha,
28
+ Pronto::BundlerAudit) # This gem's {Pronto::BundlerAudit} class.
29
+ }
30
+ end
31
+
32
+ # Pronto::BundlerAudit::Results::ProntoMessagesAdapter::DeepLine is a
33
+ # stand-in for ::Pronto::Git::Line object.
34
+ class DeepLine
35
+ attr_reader :line_number,
36
+ :path
37
+
38
+ def initialize(line_number:, path:)
39
+ @line_number = line_number
40
+ @path = path
41
+ end
42
+
43
+ # Since we're not passing a commit SHA into ::Pronto::Message.new,
44
+ # Pronto will try calling #commit_sha on the (this) Line object.
45
+ def commit_sha
46
+ nil
47
+ end
48
+
49
+ def line
50
+ self
51
+ end
52
+
53
+ alias_method :new_lineno, :line_number
54
+ alias_method :repo, :itself
55
+ alias_method :patch, :itself
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -1,46 +1,44 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "base_result"
4
- require "pronto/bundler_audit/advisory_formatters/verbose"
5
4
  require "pronto/bundler_audit/advisory_formatters/compact"
5
+ require "pronto/bundler_audit/advisory_formatters/verbose"
6
+ require "pronto/bundler_audit/gemfile_lock/scanner"
6
7
 
7
8
  module Pronto
8
9
  class BundlerAudit
9
10
  module Results
10
- # Pronto::BundlerAudit::Results::UnpatchedGem builds a Pronto::Message for
11
- # Bundler::Audit::Scanner::UnpatchedGem issues.
11
+ # Pronto::BundlerAudit::Results::UnpatchedGem is a stand-in for the
12
+ # ::Pronto::Message object for ::Bundler::Audit::Scanner::UnpatchedGem
13
+ # issues.
12
14
  class UnpatchedGem < BaseResult
13
- def initialize(scan_result, patch:)
14
- super(scan_result)
15
- @patch = patch
15
+ # @return [Symbol]
16
+ def level
17
+ :error
16
18
  end
17
19
 
18
- private
19
-
20
- def report_result
21
- build_message(
22
- message,
23
- level: :error,
24
- line: find_relevant_line)
20
+ # @return [Integer]
21
+ def line
22
+ find_relevant_line_number
25
23
  end
26
24
 
27
- # @return [Pronto::Git::Line]
28
- def find_relevant_line
29
- first_added_line_for_affected_gem_name(@gem.name)
25
+ # @return [String]
26
+ def message
27
+ advisory_formatter.to_s
30
28
  end
31
29
 
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
30
+ private
36
31
 
37
- def message
38
- advisory_formatter.to_s
32
+ # @return [Integer]
33
+ def find_relevant_line_number
34
+ Pronto::BundlerAudit::GemfileLock::Scanner.call(gem_name: @gem.name)
39
35
  end
40
36
 
41
37
  def advisory_formatter
42
38
  # TODO: Switch type based on configuration options, once available.
43
- AdvisoryFormatters::Verbose.new(gem: @gem, advisory: @advisory)
39
+ Pronto::BundlerAudit::AdvisoryFormatters::Verbose.new(
40
+ gem: @gem,
41
+ advisory: @advisory)
44
42
  end
45
43
  end
46
44
  end
@@ -2,41 +2,65 @@
2
2
 
3
3
  require_relative "results/insecure_source"
4
4
  require_relative "results/unpatched_gem"
5
+ require "yaml"
5
6
 
6
7
  module Pronto
7
8
  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.
9
+ # Pronto::BundlerAudit::Scanner runs runs Bundler::Audit::Scanner#scan and
10
+ # then instantiates and calls an appropriate
11
+ # {Pronto::BundlerAudit::BaseResult} object for the given scan result type.
11
12
  class Scanner
12
- def initialize(patch)
13
- @patch = patch
13
+ def self.call(*args)
14
+ new(*args).call
14
15
  end
15
16
 
16
- # @return [Array>] if no advisories were found
17
- # @return [Array<Pronto::Message>] if advisories were found)
17
+ # @return [Array<>] if no issues were found
18
+ # @return [Array<Pronto::BundlerAudit::Results::BaseResult>] if unpatched
19
+ # gem sources or if advisories were found
18
20
  def call
19
21
  run_scan
20
22
  end
21
23
 
22
24
  private
23
25
 
26
+ # @return [Array<>] if no issues were found
27
+ # @return [Array<Pronto::BundlerAudit::Results::BaseResult>]
24
28
  def run_scan
25
29
  run_scanner.map do |scan_result|
26
- match_result(scan_result).call
30
+ match_result(scan_result)
27
31
  end
28
32
  end
29
33
 
30
- def run_scanner
31
- Bundler::Audit::Scanner.new.scan
34
+ # Invoke the 3rd-party bundler-audit Gem.
35
+ #
36
+ # @param ignore_advisories [Array<String>] the advisories to be ignored
37
+ # by the bundler_audit scan
38
+ #
39
+ # @return [Array] if insecure sources are found or if gems with an
40
+ # advisory are found, the Array will contain
41
+ # ::Bundler::Audit::Scanner::InsecureSource
42
+ # or ::Bundler::Audit::Scanner::UnpatchedGem objects, respectively.
43
+ # - Bundler::Audit::Scanner::InsecureSource = Struct.new(:source)
44
+ # - Bundler::Audit::Scanner::UnpatchedGem = Struct.new(:gem, :advisory)
45
+ def run_scanner(
46
+ ignored_advisories:
47
+ Pronto::BundlerAudit.configuration.ignored_advisories)
48
+ ::Bundler::Audit::Scanner.new.scan(ignore: ignored_advisories)
32
49
  end
33
50
 
51
+ # Convert the passed in `scan_result` class/value into a local Results::*
52
+ # class/value.
53
+ #
54
+ # @param scan_result [::Bundler::Audit::Scanner::*] from the bundler-audit
55
+ # Gem
56
+ #
57
+ # @return [Pronto::BundlerAudit::Results::BaseResult]
34
58
  def match_result(scan_result)
35
59
  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)
60
+ when ::Bundler::Audit::Results::InsecureSource
61
+ Pronto::BundlerAudit::Results::InsecureSource.new(scan_result)
62
+ when ::Bundler::Audit::Results::UnpatchedGem
63
+ Pronto::BundlerAudit::Results::UnpatchedGem.new(scan_result)
40
64
  else
41
65
  raise ArgumentError, "Unexpected type: #{scan_result.class}"
42
66
  end
@@ -3,6 +3,6 @@
3
3
  module Pronto
4
4
  # Pronto::BundlerAuditVersion
5
5
  module BundlerAuditVersion
6
- VERSION = "0.3.0"
6
+ VERSION = "0.7.0"
7
7
  end
8
8
  end
@@ -27,8 +27,8 @@ Gem::Specification.new do |spec|
27
27
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
28
  spec.require_paths = ["lib"]
29
29
 
30
- spec.add_runtime_dependency "bundler-audit", "~> 0"
31
- spec.add_runtime_dependency "pronto", "~> 0"
30
+ spec.add_runtime_dependency "bundler-audit", "~> 0.8"
31
+ spec.add_runtime_dependency "pronto", "~> 0.11"
32
32
 
33
33
  spec.add_development_dependency "bundler", "~> 2"
34
34
  spec.add_development_dependency "byebug", "~> 11"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pronto-bundler_audit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.7.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-05-03 00:00:00.000000000 Z
11
+ date: 2021-04-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler-audit
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '0.8'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: '0.8'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: pronto
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: '0.11'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: '0.11'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: bundler
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -203,15 +203,21 @@ files:
203
203
  - Rakefile
204
204
  - bin/console
205
205
  - bin/setup
206
+ - images/ci-output.png
206
207
  - images/github-check.png
207
- - images/github-comment.png
208
+ - images/github-comment-compact.png
209
+ - images/github-comment-verbose.png
210
+ - lib/formatter/github_pull_request_review_formatter.rb
208
211
  - lib/pronto/bundler_audit.rb
209
212
  - lib/pronto/bundler_audit/advisory_formatters/base_advisory_formatter.rb
210
213
  - lib/pronto/bundler_audit/advisory_formatters/compact.rb
211
214
  - lib/pronto/bundler_audit/advisory_formatters/verbose.rb
212
215
  - lib/pronto/bundler_audit/auditor.rb
216
+ - lib/pronto/bundler_audit/configuration.rb
217
+ - lib/pronto/bundler_audit/gemfile_lock/scanner.rb
213
218
  - lib/pronto/bundler_audit/results/base_result.rb
214
219
  - lib/pronto/bundler_audit/results/insecure_source.rb
220
+ - lib/pronto/bundler_audit/results/pronto_messages_adapter.rb
215
221
  - lib/pronto/bundler_audit/results/unpatched_gem.rb
216
222
  - lib/pronto/bundler_audit/scanner.rb
217
223
  - lib/pronto/bundler_audit/version.rb
@@ -235,7 +241,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
235
241
  - !ruby/object:Gem::Version
236
242
  version: '0'
237
243
  requirements: []
238
- rubygems_version: 3.0.3
244
+ rubygems_version: 3.0.3.1
239
245
  signing_key:
240
246
  specification_version: 4
241
247
  summary: Pronto runner for bundler-audit, patch-level verification for bundler.