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 +4 -4
- data/.rubocop.yml +3 -0
- data/.travis.yml +1 -2
- data/CHANGELOG.md +30 -1
- data/Gemfile.lock +45 -34
- data/README.md +67 -9
- data/images/ci-output.png +0 -0
- data/images/{github-comment.png → github-comment-compact.png} +0 -0
- data/images/github-comment-verbose.png +0 -0
- data/lib/formatter/github_pull_request_review_formatter.rb +36 -0
- data/lib/pronto/bundler_audit.rb +33 -22
- data/lib/pronto/bundler_audit/auditor.rb +10 -10
- data/lib/pronto/bundler_audit/configuration.rb +34 -0
- data/lib/pronto/bundler_audit/gemfile_lock/scanner.rb +45 -0
- data/lib/pronto/bundler_audit/results/base_result.rb +10 -15
- data/lib/pronto/bundler_audit/results/insecure_source.rb +11 -8
- data/lib/pronto/bundler_audit/results/pronto_messages_adapter.rb +60 -0
- data/lib/pronto/bundler_audit/results/unpatched_gem.rb +21 -23
- data/lib/pronto/bundler_audit/scanner.rb +38 -14
- data/lib/pronto/bundler_audit/version.rb +1 -1
- data/pronto-bundler_audit.gemspec +2 -2
- metadata +14 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8112a836fbdf9cfbedc584f8a6f6546da622fea402df4be5e6a21b883504377e
|
4
|
+
data.tar.gz: 1e2c2c4e8144bc9c1dbc8d2c84887a0419d95570e357b92054ff73400517c095
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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.
|
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.
|
12
|
-
public_suffix (>= 2.0.2, <
|
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.
|
16
|
+
bundler-audit (0.8.0)
|
17
17
|
bundler (>= 1.2.0, < 3)
|
18
|
-
thor (~> 0
|
18
|
+
thor (~> 1.0)
|
19
19
|
byebug (11.0.1)
|
20
20
|
coderay (1.1.2)
|
21
|
-
docile (1.3.
|
22
|
-
faraday (
|
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
|
-
|
25
|
-
|
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.
|
34
|
+
httparty (0.18.1)
|
28
35
|
mime-types (~> 3.0)
|
29
36
|
multi_xml (>= 0.5.2)
|
30
|
-
jaro_winkler (1.5.
|
31
|
-
json (2.
|
37
|
+
jaro_winkler (1.5.3)
|
38
|
+
json (2.3.1)
|
32
39
|
method_source (0.9.2)
|
33
|
-
mime-types (3.
|
40
|
+
mime-types (3.3.1)
|
34
41
|
mime-types-data (~> 3.2015)
|
35
|
-
mime-types-data (3.
|
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.
|
49
|
+
much-stub (0.1.1)
|
43
50
|
multi_xml (0.6.0)
|
44
|
-
multipart-post (2.
|
45
|
-
octokit (4.
|
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.
|
51
|
-
gitlab (~> 4.
|
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
|
-
|
56
|
-
|
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 (
|
72
|
+
public_suffix (4.0.6)
|
64
73
|
rainbow (3.0.0)
|
65
|
-
rake (12.3.
|
66
|
-
|
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.
|
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.
|
73
|
-
ruby-progressbar (1.10.
|
74
|
-
|
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.
|
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 (
|
86
|
-
unicode-display_width (1.
|
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.
|
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
|
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
|
-
|
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
|
-
|
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
|
-
$
|
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
|
-
|
49
|
-
|
50
|
-
|
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
|
-
|
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
|
File without changes
|
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
|
data/lib/pronto/bundler_audit.rb
CHANGED
@@ -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.
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
|
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
|
-
|
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
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
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
|
-
|
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
|
30
|
-
|
31
|
-
patch.additions > 0 && relevant_patch_path?(patch)
|
32
|
-
}
|
38
|
+
def filename
|
39
|
+
GEMFILE_LOCK_FILENAME
|
33
40
|
end
|
34
41
|
|
35
|
-
|
36
|
-
|
37
|
-
|
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.
|
9
|
-
# 2.
|
8
|
+
# 1. Updates the local ruby security database, and then
|
9
|
+
# 2. Runs {::Pronto::BundlerAudit::Scanner#call}.
|
10
10
|
class Auditor
|
11
|
-
def
|
12
|
-
|
11
|
+
def self.call(*args)
|
12
|
+
new(*args).call
|
13
13
|
end
|
14
14
|
|
15
|
-
# @return (see: #
|
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
|
28
|
-
# @return [Array<Pronto::
|
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
|
-
|
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
|
-
|
16
|
-
|
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
|
-
|
26
|
-
|
27
|
-
|
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
|
9
|
-
# for Bundler::Audit::Scanner::InsecureSource
|
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
|
-
|
12
|
+
# @return [Symbol]
|
13
|
+
def level
|
14
|
+
:warning
|
15
|
+
end
|
12
16
|
|
13
|
-
|
14
|
-
|
15
|
-
|
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
|
11
|
-
# Bundler::Audit::Scanner::UnpatchedGem
|
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
|
-
|
14
|
-
|
15
|
-
|
15
|
+
# @return [Symbol]
|
16
|
+
def level
|
17
|
+
:error
|
16
18
|
end
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
-
|
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 [
|
28
|
-
def
|
29
|
-
|
25
|
+
# @return [String]
|
26
|
+
def message
|
27
|
+
advisory_formatter.to_s
|
30
28
|
end
|
31
29
|
|
32
|
-
|
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
|
-
|
38
|
-
|
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(
|
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
|
9
|
-
#
|
10
|
-
# for
|
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
|
13
|
-
|
13
|
+
def self.call(*args)
|
14
|
+
new(*args).call
|
14
15
|
end
|
15
16
|
|
16
|
-
# @return [Array
|
17
|
-
# @return [Array<Pronto::
|
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)
|
30
|
+
match_result(scan_result)
|
27
31
|
end
|
28
32
|
end
|
29
33
|
|
30
|
-
|
31
|
-
|
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::
|
37
|
-
Results::InsecureSource.new(scan_result
|
38
|
-
when Bundler::Audit::
|
39
|
-
Results::UnpatchedGem.new(scan_result
|
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
|
@@ -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.
|
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:
|
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.
|