bundler-audit 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/.travis.yml +5 -3
- data/ChangeLog.md +15 -0
- data/Gemfile +2 -1
- data/README.md +8 -1
- data/Rakefile +3 -13
- data/gemspec.yml +1 -0
- data/lib/bundler/audit.rb +1 -1
- data/lib/bundler/audit/advisory.rb +5 -1
- data/lib/bundler/audit/cli.rb +9 -4
- data/lib/bundler/audit/database.rb +2 -2
- data/lib/bundler/audit/scanner.rb +101 -3
- data/lib/bundler/audit/version.rb +2 -2
- data/spec/advisory_spec.rb +51 -25
- data/spec/audit_spec.rb +1 -1
- data/spec/bundle/insecure_sources/Gemfile +1 -1
- data/spec/bundle/secure/Gemfile +1 -1
- data/spec/bundle/unpatched_gems/Gemfile +1 -1
- data/spec/database_spec.rb +10 -10
- data/spec/integration_spec.rb +6 -6
- data/spec/scanner_spec.rb +8 -8
- data/spec/spec_helper.rb +7 -4
- metadata +33 -33
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9660b06fce10c2532f0c7aaa5fef6ca2d5c99067
|
|
4
|
+
data.tar.gz: 751d7e542727defa267b6d8abf2ad0b3f391ab70
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2a3cb90acc0cecc82ee931fedd43ab4d0439fd2436bc29563a45a4a328862c9038f243f7bff68a9e394bb0c12fee6f83b1496347187783b3a6d972435169dbf3
|
|
7
|
+
data.tar.gz: 89a771db86e3baf43430b5448bee5664e1b73f017fed9c48756ea8a58f6f4515c761d4c46333a93e9bcde71e3c6777271ec799a933d5662a76df9504a29dd09d
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/ChangeLog.md
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
### 0.4.0 / 2015-06-30
|
|
2
|
+
|
|
3
|
+
* Require ruby >= 1.9.3 due to i18n gem deprecating < 1.9.3.
|
|
4
|
+
* Added {Bundler::Audit::Advisory#osvdb}.
|
|
5
|
+
* Resolve the IP addresses of gem sources and ignore intranet gem sources.
|
|
6
|
+
(PR #90)
|
|
7
|
+
* Use ISO8601 date format when querying the git timestamp of ruby-advisory-db.
|
|
8
|
+
(PR #92)
|
|
9
|
+
|
|
10
|
+
#### CLI
|
|
11
|
+
|
|
12
|
+
* Print the CVE or OSVDB id.
|
|
13
|
+
* No longer print "Unpatched versions found!" when an insecure gem source
|
|
14
|
+
is detected. (PR #84)
|
|
15
|
+
|
|
1
16
|
### 0.3.1 / 2014-04-20
|
|
2
17
|
|
|
3
18
|
* Added thor ~> 0.18 as a dependency.
|
data/Gemfile
CHANGED
data/README.md
CHANGED
|
@@ -108,8 +108,13 @@ Update the [ruby-advisory-db] that `bundle-audit` uses:
|
|
|
108
108
|
create mode 100644 gems/wicked/OSVDB-98270.yml
|
|
109
109
|
ruby-advisory-db: 64 advisories
|
|
110
110
|
|
|
111
|
+
Ignore specific advisories:
|
|
112
|
+
|
|
113
|
+
$ bundle-audit check --ignore OSVDB-108664
|
|
114
|
+
|
|
111
115
|
## Requirements
|
|
112
116
|
|
|
117
|
+
* [Ruby] >= 1.9.3
|
|
113
118
|
* [RubyGems] >= 1.8
|
|
114
119
|
* [thor] ~> 0.18
|
|
115
120
|
* [bundler] ~> 1.2
|
|
@@ -120,7 +125,7 @@ Update the [ruby-advisory-db] that `bundle-audit` uses:
|
|
|
120
125
|
|
|
121
126
|
## License
|
|
122
127
|
|
|
123
|
-
Copyright (c) 2013-
|
|
128
|
+
Copyright (c) 2013-2015 Hal Brodigan (postmodern.mod3 at gmail.com)
|
|
124
129
|
|
|
125
130
|
bundler-audit is free software: you can redistribute it and/or modify
|
|
126
131
|
it under the terms of the GNU General Public License as published by
|
|
@@ -135,8 +140,10 @@ GNU General Public License for more details.
|
|
|
135
140
|
You should have received a copy of the GNU General Public License
|
|
136
141
|
along with bundler-audit. If not, see <http://www.gnu.org/licenses/>.
|
|
137
142
|
|
|
143
|
+
[Ruby]: https://ruby-lang.org
|
|
138
144
|
[RubyGems]: https://rubygems.org
|
|
139
145
|
[thor]: http://whatisthor.com/
|
|
140
146
|
[bundler]: https://github.com/carlhuda/bundler#readme
|
|
141
147
|
|
|
142
148
|
[OSVDB]: http://osvdb.org/
|
|
149
|
+
[ruby-advisory-db]: https://github.com/rubysec/ruby-advisory-db
|
data/Rakefile
CHANGED
|
@@ -3,19 +3,9 @@
|
|
|
3
3
|
require 'rubygems'
|
|
4
4
|
|
|
5
5
|
begin
|
|
6
|
-
require 'bundler'
|
|
6
|
+
require 'bundler/setup'
|
|
7
7
|
rescue LoadError => e
|
|
8
|
-
|
|
9
|
-
warn "Run `gem install bundler` to install Bundler."
|
|
10
|
-
exit -1
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
begin
|
|
14
|
-
Bundler.setup(:development)
|
|
15
|
-
rescue Bundler::BundlerError => e
|
|
16
|
-
warn e.message
|
|
17
|
-
warn "Run `bundle install` to install missing gems."
|
|
18
|
-
exit e.status_code
|
|
8
|
+
abort e.message
|
|
19
9
|
end
|
|
20
10
|
|
|
21
11
|
require 'rake'
|
|
@@ -52,7 +42,7 @@ namespace :spec do
|
|
|
52
42
|
|
|
53
43
|
%w[secure unpatched_gems insecure_sources].each do |bundle|
|
|
54
44
|
chdir(File.join(root,bundle)) do
|
|
55
|
-
sh 'BUNDLE_BIN_PATH
|
|
45
|
+
sh 'unset BUNDLE_BIN_PATH BUNDLE_GEMFILE RUBYOPT && bundle install --path ../../../vendor/bundle'
|
|
56
46
|
end
|
|
57
47
|
end
|
|
58
48
|
end
|
data/gemspec.yml
CHANGED
data/lib/bundler/audit.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#
|
|
2
|
-
# Copyright (c) 2013-
|
|
2
|
+
# Copyright (c) 2013-2015 Hal Brodigan (postmodern.mod3 at gmail.com)
|
|
3
3
|
#
|
|
4
4
|
# bundler-audit is free software: you can redistribute it and/or modify
|
|
5
5
|
# it under the terms of the GNU General Public License as published by
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#
|
|
2
|
-
# Copyright (c) 2013-
|
|
2
|
+
# Copyright (c) 2013-2015 Hal Brodigan (postmodern.mod3 at gmail.com)
|
|
3
3
|
#
|
|
4
4
|
# bundler-audit is free software: you can redistribute it and/or modify
|
|
5
5
|
# it under the terms of the GNU General Public License as published by
|
|
@@ -25,6 +25,8 @@ module Bundler
|
|
|
25
25
|
:title,
|
|
26
26
|
:description,
|
|
27
27
|
:cvss_v2,
|
|
28
|
+
:cve,
|
|
29
|
+
:osvdb,
|
|
28
30
|
:unaffected_versions,
|
|
29
31
|
:patched_versions)
|
|
30
32
|
|
|
@@ -59,6 +61,8 @@ module Bundler
|
|
|
59
61
|
data['title'],
|
|
60
62
|
data['description'],
|
|
61
63
|
data['cvss_v2'],
|
|
64
|
+
data['cve'],
|
|
65
|
+
data['osvdb'],
|
|
62
66
|
parse_versions[data['unaffected_versions']],
|
|
63
67
|
parse_versions[data['patched_versions']]
|
|
64
68
|
)
|
data/lib/bundler/audit/cli.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#
|
|
2
|
-
# Copyright (c) 2013-
|
|
2
|
+
# Copyright (c) 2013-2015 Hal Brodigan (postmodern.mod3 at gmail.com)
|
|
3
3
|
#
|
|
4
4
|
# bundler-audit is free software: you can redistribute it and/or modify
|
|
5
5
|
# it under the terms of the GNU General Public License as published by
|
|
@@ -49,10 +49,10 @@ module Bundler
|
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
if vulnerable
|
|
52
|
-
say "
|
|
52
|
+
say "Vulnerabilities found!", :red
|
|
53
53
|
exit 1
|
|
54
54
|
else
|
|
55
|
-
say "No
|
|
55
|
+
say "No vulnerabilities found", :green
|
|
56
56
|
end
|
|
57
57
|
end
|
|
58
58
|
|
|
@@ -90,7 +90,12 @@ module Bundler
|
|
|
90
90
|
say gem.version
|
|
91
91
|
|
|
92
92
|
say "Advisory: ", :red
|
|
93
|
-
|
|
93
|
+
|
|
94
|
+
if advisory.cve
|
|
95
|
+
say "CVE-#{advisory.cve}"
|
|
96
|
+
elsif advisory.osvdb
|
|
97
|
+
say advisory.osvdb
|
|
98
|
+
end
|
|
94
99
|
|
|
95
100
|
say "Criticality: ", :red
|
|
96
101
|
case advisory.criticality
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#
|
|
2
|
-
# Copyright (c) 2013-
|
|
2
|
+
# Copyright (c) 2013-2015 Hal Brodigan (postmodern.mod3 at gmail.com)
|
|
3
3
|
#
|
|
4
4
|
# bundler-audit is free software: you can redistribute it and/or modify
|
|
5
5
|
# it under the terms of the GNU General Public License as published by
|
|
@@ -68,7 +68,7 @@ module Bundler
|
|
|
68
68
|
#
|
|
69
69
|
def self.path
|
|
70
70
|
if File.directory?(USER_PATH)
|
|
71
|
-
t1 = Dir.chdir(USER_PATH) { Time.parse(`git log --pretty="%cd" -1`) }
|
|
71
|
+
t1 = Dir.chdir(USER_PATH) { Time.parse(`git log --date=iso8601 --pretty="%cd" -1`) }
|
|
72
72
|
t2 = VENDORED_TIMESTAMP
|
|
73
73
|
|
|
74
74
|
if t1 >= t2 then USER_PATH
|
|
@@ -2,7 +2,10 @@ require 'bundler'
|
|
|
2
2
|
require 'bundler/audit/database'
|
|
3
3
|
require 'bundler/lockfile_parser'
|
|
4
4
|
|
|
5
|
+
require 'ipaddr'
|
|
6
|
+
require 'resolv'
|
|
5
7
|
require 'set'
|
|
8
|
+
require 'uri'
|
|
6
9
|
|
|
7
10
|
module Bundler
|
|
8
11
|
module Audit
|
|
@@ -59,17 +62,46 @@ module Bundler
|
|
|
59
62
|
# @return [Enumerator]
|
|
60
63
|
# If no block is given, an Enumerator will be returned.
|
|
61
64
|
#
|
|
62
|
-
def scan(options={})
|
|
63
|
-
return enum_for(__method__,options) unless
|
|
65
|
+
def scan(options={},&block)
|
|
66
|
+
return enum_for(__method__,options) unless block
|
|
64
67
|
|
|
65
68
|
ignore = Set[]
|
|
66
69
|
ignore += options[:ignore] if options[:ignore]
|
|
67
70
|
|
|
71
|
+
scan_sources(options,&block)
|
|
72
|
+
scan_specs(options,&block)
|
|
73
|
+
|
|
74
|
+
return self
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
#
|
|
78
|
+
# Scans the gem sources in the lockfile.
|
|
79
|
+
#
|
|
80
|
+
# @param [Hash] options
|
|
81
|
+
# Additional options.
|
|
82
|
+
#
|
|
83
|
+
# @yield [result]
|
|
84
|
+
# The given block will be passed the results of the scan.
|
|
85
|
+
#
|
|
86
|
+
# @yieldparam [InsecureSource] result
|
|
87
|
+
# A result from the scan.
|
|
88
|
+
#
|
|
89
|
+
# @return [Enumerator]
|
|
90
|
+
# If no block is given, an Enumerator will be returned.
|
|
91
|
+
#
|
|
92
|
+
# @api semipublic
|
|
93
|
+
#
|
|
94
|
+
# @since 0.4.0
|
|
95
|
+
#
|
|
96
|
+
def scan_sources(options={})
|
|
97
|
+
return enum_for(__method__,options) unless block_given?
|
|
98
|
+
|
|
68
99
|
@lockfile.sources.map do |source|
|
|
69
100
|
case source
|
|
70
101
|
when Source::Git
|
|
71
102
|
case source.uri
|
|
72
103
|
when /^git:/, /^http:/
|
|
104
|
+
next if internal_host?(source.uri)
|
|
73
105
|
yield InsecureSource.new(source.uri)
|
|
74
106
|
end
|
|
75
107
|
when Source::Rubygems
|
|
@@ -80,6 +112,35 @@ module Bundler
|
|
|
80
112
|
end
|
|
81
113
|
end
|
|
82
114
|
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
#
|
|
118
|
+
# Scans the gem sources in the lockfile.
|
|
119
|
+
#
|
|
120
|
+
# @param [Hash] options
|
|
121
|
+
# Additional options.
|
|
122
|
+
#
|
|
123
|
+
# @option options [Array<String>] :ignore
|
|
124
|
+
# The advisories to ignore.
|
|
125
|
+
#
|
|
126
|
+
# @yield [result]
|
|
127
|
+
# The given block will be passed the results of the scan.
|
|
128
|
+
#
|
|
129
|
+
# @yieldparam [UnpatchedGem] result
|
|
130
|
+
# A result from the scan.
|
|
131
|
+
#
|
|
132
|
+
# @return [Enumerator]
|
|
133
|
+
# If no block is given, an Enumerator will be returned.
|
|
134
|
+
#
|
|
135
|
+
# @api semipublic
|
|
136
|
+
#
|
|
137
|
+
# @since 0.4.0
|
|
138
|
+
#
|
|
139
|
+
def scan_specs(options={})
|
|
140
|
+
return enum_for(__method__,options) unless block_given?
|
|
141
|
+
|
|
142
|
+
ignore = Set[]
|
|
143
|
+
ignore += options[:ignore] if options[:ignore]
|
|
83
144
|
|
|
84
145
|
@lockfile.specs.each do |gem|
|
|
85
146
|
@database.check_gem(gem) do |advisory|
|
|
@@ -88,10 +149,47 @@ module Bundler
|
|
|
88
149
|
end
|
|
89
150
|
end
|
|
90
151
|
end
|
|
152
|
+
end
|
|
91
153
|
|
|
92
|
-
|
|
154
|
+
private
|
|
155
|
+
|
|
156
|
+
#
|
|
157
|
+
# Determines whether a URI is internal.
|
|
158
|
+
#
|
|
159
|
+
# @param [String] uri
|
|
160
|
+
# The source URI.
|
|
161
|
+
#
|
|
162
|
+
# @return [Boolean]
|
|
163
|
+
#
|
|
164
|
+
def internal_host?(uri)
|
|
165
|
+
return unless host = URI.parse(uri).host
|
|
166
|
+
Resolv.getaddresses(host).all? { |ip| internal_ip?(ip) }
|
|
167
|
+
rescue URI::Error
|
|
168
|
+
false
|
|
93
169
|
end
|
|
94
170
|
|
|
171
|
+
# List of internal IP address ranges.
|
|
172
|
+
#
|
|
173
|
+
# @see https://tools.ietf.org/html/rfc1918#section-3
|
|
174
|
+
# @see https://tools.ietf.org/html/rfc4193#section-8
|
|
175
|
+
INTERNAL_SUBNETS = %w[
|
|
176
|
+
10.0.0.0/8
|
|
177
|
+
172.16.0.0/12
|
|
178
|
+
192.168.0.0/16
|
|
179
|
+
fc00::/7
|
|
180
|
+
].map(&IPAddr.method(:new))
|
|
181
|
+
|
|
182
|
+
#
|
|
183
|
+
# Determines whether an IP is internal.
|
|
184
|
+
#
|
|
185
|
+
# @param [String] ip
|
|
186
|
+
# The IPv4/IPv6 address.
|
|
187
|
+
#
|
|
188
|
+
# @return [Boolean]
|
|
189
|
+
#
|
|
190
|
+
def internal_ip?(ip)
|
|
191
|
+
INTERNAL_SUBNETS.any? { |subnet| subnet.include?(ip) }
|
|
192
|
+
end
|
|
95
193
|
end
|
|
96
194
|
end
|
|
97
195
|
end
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#
|
|
2
|
-
# Copyright (c) 2013-
|
|
2
|
+
# Copyright (c) 2013-2015 Hal Brodigan (postmodern.mod3 at gmail.com)
|
|
3
3
|
#
|
|
4
4
|
# bundler-audit is free software: you can redistribute it and/or modify
|
|
5
5
|
# it under the terms of the GNU General Public License as published by
|
|
@@ -18,6 +18,6 @@
|
|
|
18
18
|
module Bundler
|
|
19
19
|
module Audit
|
|
20
20
|
# bundler-audit version
|
|
21
|
-
VERSION = '0.
|
|
21
|
+
VERSION = '0.4.0'
|
|
22
22
|
end
|
|
23
23
|
end
|
data/spec/advisory_spec.rb
CHANGED
|
@@ -29,11 +29,30 @@ describe Bundler::Audit::Advisory do
|
|
|
29
29
|
|
|
30
30
|
subject { described_class.load(path) }
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
describe '#id' do
|
|
33
|
+
subject { super().id }
|
|
34
|
+
it { is_expected.to eq(id) }
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
describe '#url' do
|
|
38
|
+
subject { super().url }
|
|
39
|
+
it { is_expected.to eq(data['url']) }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
describe '#title' do
|
|
43
|
+
subject { super().title }
|
|
44
|
+
it { is_expected.to eq(data['title']) }
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
describe '#cvss_v2' do
|
|
48
|
+
subject { super().cvss_v2 }
|
|
49
|
+
it { is_expected.to eq(data['cvss_v2']) }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
describe '#description' do
|
|
53
|
+
subject { super().description }
|
|
54
|
+
it { is_expected.to eq(data['description']) }
|
|
55
|
+
end
|
|
37
56
|
|
|
38
57
|
context "YAML data not representing a hash" do
|
|
39
58
|
it "should raise an exception" do
|
|
@@ -48,34 +67,41 @@ describe Bundler::Audit::Advisory do
|
|
|
48
67
|
subject { described_class.load(path).patched_versions }
|
|
49
68
|
|
|
50
69
|
it "should all be Gem::Requirement objects" do
|
|
51
|
-
subject.all? { |version|
|
|
52
|
-
version.
|
|
53
|
-
}.
|
|
70
|
+
expect(subject.all? { |version|
|
|
71
|
+
expect(version).to be_kind_of(Gem::Requirement)
|
|
72
|
+
}).to be_truthy
|
|
54
73
|
end
|
|
55
74
|
|
|
56
75
|
it "should parse the versions" do
|
|
57
|
-
subject.map(&:to_s).
|
|
76
|
+
expect(subject.map(&:to_s)).to eq(data['patched_versions'])
|
|
58
77
|
end
|
|
59
78
|
end
|
|
60
79
|
end
|
|
61
80
|
|
|
62
81
|
describe "#criticality" do
|
|
63
82
|
context "when cvss_v2 is between 0.0 and 3.3" do
|
|
64
|
-
before {
|
|
65
|
-
|
|
66
|
-
|
|
83
|
+
before {
|
|
84
|
+
@advisory = Advisory.new
|
|
85
|
+
@advisory.cvss_v2 = 3.3
|
|
86
|
+
}
|
|
87
|
+
it { expect(@advisory.criticality).to eq(:low) }
|
|
67
88
|
end
|
|
68
89
|
|
|
69
90
|
context "when cvss_v2 is between 3.3 and 6.6" do
|
|
70
|
-
before {
|
|
91
|
+
before {
|
|
92
|
+
@advisory = Advisory.new
|
|
93
|
+
@advisory.cvss_v2 = 6.6
|
|
94
|
+
}
|
|
95
|
+
it { expect(@advisory.criticality).to eq(:medium) }
|
|
71
96
|
|
|
72
|
-
its(:criticality) { should == :medium }
|
|
73
97
|
end
|
|
74
98
|
|
|
75
99
|
context "when cvss_v2 is between 6.6 and 10.0" do
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
100
|
+
before {
|
|
101
|
+
@advisory = Advisory.new
|
|
102
|
+
@advisory.cvss_v2 = 10.0
|
|
103
|
+
}
|
|
104
|
+
it { expect(@advisory.criticality).to eq(:high) }
|
|
79
105
|
end
|
|
80
106
|
end
|
|
81
107
|
|
|
@@ -86,7 +112,7 @@ describe Bundler::Audit::Advisory do
|
|
|
86
112
|
let(:version) { Gem::Version.new(an_unaffected_version) }
|
|
87
113
|
|
|
88
114
|
it "should return true" do
|
|
89
|
-
subject.unaffected?(version).
|
|
115
|
+
expect(subject.unaffected?(version)).to be_truthy
|
|
90
116
|
end
|
|
91
117
|
end
|
|
92
118
|
|
|
@@ -94,7 +120,7 @@ describe Bundler::Audit::Advisory do
|
|
|
94
120
|
let(:version) { Gem::Version.new('3.0.9') }
|
|
95
121
|
|
|
96
122
|
it "should return false" do
|
|
97
|
-
subject.unaffected?(version).
|
|
123
|
+
expect(subject.unaffected?(version)).to be_falsey
|
|
98
124
|
end
|
|
99
125
|
end
|
|
100
126
|
end
|
|
@@ -106,7 +132,7 @@ describe Bundler::Audit::Advisory do
|
|
|
106
132
|
let(:version) { Gem::Version.new('3.1.11') }
|
|
107
133
|
|
|
108
134
|
it "should return true" do
|
|
109
|
-
subject.patched?(version).
|
|
135
|
+
expect(subject.patched?(version)).to be_truthy
|
|
110
136
|
end
|
|
111
137
|
end
|
|
112
138
|
|
|
@@ -114,7 +140,7 @@ describe Bundler::Audit::Advisory do
|
|
|
114
140
|
let(:version) { Gem::Version.new('2.9.0') }
|
|
115
141
|
|
|
116
142
|
it "should return false" do
|
|
117
|
-
subject.patched?(version).
|
|
143
|
+
expect(subject.patched?(version)).to be_falsey
|
|
118
144
|
end
|
|
119
145
|
end
|
|
120
146
|
end
|
|
@@ -126,7 +152,7 @@ describe Bundler::Audit::Advisory do
|
|
|
126
152
|
let(:version) { Gem::Version.new('3.1.11') }
|
|
127
153
|
|
|
128
154
|
it "should return false" do
|
|
129
|
-
subject.vulnerable?(version).
|
|
155
|
+
expect(subject.vulnerable?(version)).to be_falsey
|
|
130
156
|
end
|
|
131
157
|
end
|
|
132
158
|
|
|
@@ -134,7 +160,7 @@ describe Bundler::Audit::Advisory do
|
|
|
134
160
|
let(:version) { Gem::Version.new('2.9.0') }
|
|
135
161
|
|
|
136
162
|
it "should return true" do
|
|
137
|
-
subject.vulnerable?(version).
|
|
163
|
+
expect(subject.vulnerable?(version)).to be_truthy
|
|
138
164
|
end
|
|
139
165
|
|
|
140
166
|
context "when unaffected_versions is not empty" do
|
|
@@ -144,7 +170,7 @@ describe Bundler::Audit::Advisory do
|
|
|
144
170
|
let(:version) { Gem::Version.new(an_unaffected_version) }
|
|
145
171
|
|
|
146
172
|
it "should return false" do
|
|
147
|
-
subject.vulnerable?(version).
|
|
173
|
+
expect(subject.vulnerable?(version)).to be_falsey
|
|
148
174
|
end
|
|
149
175
|
end
|
|
150
176
|
|
|
@@ -152,7 +178,7 @@ describe Bundler::Audit::Advisory do
|
|
|
152
178
|
let(:version) { Gem::Version.new('1.2.3') }
|
|
153
179
|
|
|
154
180
|
it "should return true" do
|
|
155
|
-
subject.vulnerable?(version).
|
|
181
|
+
expect(subject.vulnerable?(version)).to be_truthy
|
|
156
182
|
end
|
|
157
183
|
end
|
|
158
184
|
end
|
data/spec/audit_spec.rb
CHANGED
data/spec/bundle/secure/Gemfile
CHANGED
data/spec/database_spec.rb
CHANGED
|
@@ -11,7 +11,7 @@ describe Bundler::Audit::Database do
|
|
|
11
11
|
subject { described_class.path }
|
|
12
12
|
|
|
13
13
|
it "it should be a directory" do
|
|
14
|
-
File.directory?(subject).
|
|
14
|
+
expect(File.directory?(subject)).to be_truthy
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
it "should prefer the user repo, iff it's as up to date, or more up to date than the vendored one" do
|
|
@@ -56,7 +56,7 @@ describe Bundler::Audit::Database do
|
|
|
56
56
|
subject { described_class.new }
|
|
57
57
|
|
|
58
58
|
it "should default path to path" do
|
|
59
|
-
subject.path.
|
|
59
|
+
expect(subject.path).to eq(described_class.path)
|
|
60
60
|
end
|
|
61
61
|
end
|
|
62
62
|
|
|
@@ -66,15 +66,15 @@ describe Bundler::Audit::Database do
|
|
|
66
66
|
subject { described_class.new(path) }
|
|
67
67
|
|
|
68
68
|
it "should set #path" do
|
|
69
|
-
subject.path.
|
|
69
|
+
expect(subject.path).to eq(path)
|
|
70
70
|
end
|
|
71
71
|
end
|
|
72
72
|
|
|
73
73
|
context "when given an invalid directory" do
|
|
74
74
|
it "should raise an ArgumentError" do
|
|
75
|
-
|
|
75
|
+
expect {
|
|
76
76
|
described_class.new('/foo/bar/baz')
|
|
77
|
-
}.
|
|
77
|
+
}.to raise_error(ArgumentError)
|
|
78
78
|
end
|
|
79
79
|
end
|
|
80
80
|
end
|
|
@@ -95,16 +95,16 @@ describe Bundler::Audit::Database do
|
|
|
95
95
|
advisories << advisory
|
|
96
96
|
end
|
|
97
97
|
|
|
98
|
-
advisories.
|
|
99
|
-
advisories.all? { |advisory|
|
|
98
|
+
expect(advisories).not_to be_empty
|
|
99
|
+
expect(advisories.all? { |advisory|
|
|
100
100
|
advisory.kind_of?(Bundler::Audit::Advisory)
|
|
101
|
-
}.
|
|
101
|
+
}).to be_truthy
|
|
102
102
|
end
|
|
103
103
|
end
|
|
104
104
|
|
|
105
105
|
context "when given no block" do
|
|
106
106
|
it "should return an Enumerator" do
|
|
107
|
-
subject.check_gem(gem).
|
|
107
|
+
expect(subject.check_gem(gem)).to be_kind_of(Enumerable)
|
|
108
108
|
end
|
|
109
109
|
end
|
|
110
110
|
end
|
|
@@ -126,7 +126,7 @@ describe Bundler::Audit::Database do
|
|
|
126
126
|
|
|
127
127
|
describe "#to_s" do
|
|
128
128
|
it "should return the Database path" do
|
|
129
|
-
subject.to_s.
|
|
129
|
+
expect(subject.to_s).to eq(subject.path)
|
|
130
130
|
end
|
|
131
131
|
end
|
|
132
132
|
|
data/spec/integration_spec.rb
CHANGED
|
@@ -16,20 +16,20 @@ describe "CLI" do
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
it "should print a warning" do
|
|
19
|
-
subject.
|
|
19
|
+
expect(subject).to include("Vulnerabilities found!")
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
it "should print advisory information for the vulnerable gems" do
|
|
23
23
|
advisory_pattern = /(Name: [^\n]+
|
|
24
24
|
Version: \d+.\d+.\d+
|
|
25
|
-
Advisory:
|
|
25
|
+
Advisory: CVE-[0-9]{4}-[0-9]{4}
|
|
26
26
|
Criticality: (High|Medium)
|
|
27
27
|
URL: http:\/\/(direct|www\.)?osvdb.org\/show\/osvdb\/\d+
|
|
28
28
|
Title: [^\n]*?
|
|
29
29
|
Solution: upgrade to ((~>|=>) \d+.\d+.\d+, )*(~>|=>) \d+.\d+.\d+[\s\n]*?)+/
|
|
30
30
|
|
|
31
31
|
expect(subject).to match(advisory_pattern)
|
|
32
|
-
expect(subject).to include("
|
|
32
|
+
expect(subject).to include("Vulnerabilities found!")
|
|
33
33
|
end
|
|
34
34
|
end
|
|
35
35
|
|
|
@@ -46,7 +46,7 @@ Solution: upgrade to ((~>|=>) \d+.\d+.\d+, )*(~>|=>) \d+.\d+.\d+[\s\n]*?)+/
|
|
|
46
46
|
end
|
|
47
47
|
|
|
48
48
|
it "should not print advisory information for ignored gem" do
|
|
49
|
-
subject.
|
|
49
|
+
expect(subject).not_to include("OSVDB-89026")
|
|
50
50
|
end
|
|
51
51
|
end
|
|
52
52
|
|
|
@@ -59,7 +59,7 @@ Solution: upgrade to ((~>|=>) \d+.\d+.\d+, )*(~>|=>) \d+.\d+.\d+[\s\n]*?)+/
|
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
it "should print warnings about insecure sources" do
|
|
62
|
-
subject.
|
|
62
|
+
expect(subject).to include(%{
|
|
63
63
|
Insecure Source URI found: git://github.com/rails/jquery-rails.git
|
|
64
64
|
Insecure Source URI found: http://rubygems.org/
|
|
65
65
|
}.strip)
|
|
@@ -75,7 +75,7 @@ Insecure Source URI found: http://rubygems.org/
|
|
|
75
75
|
end
|
|
76
76
|
|
|
77
77
|
it "should print nothing when everything is fine" do
|
|
78
|
-
subject.strip.
|
|
78
|
+
expect(subject.strip).to eq("No vulnerabilities found")
|
|
79
79
|
end
|
|
80
80
|
end
|
|
81
81
|
end
|
data/spec/scanner_spec.rb
CHANGED
|
@@ -13,12 +13,12 @@ describe Scanner do
|
|
|
13
13
|
|
|
14
14
|
subject.scan { |result| results << result }
|
|
15
15
|
|
|
16
|
-
results.
|
|
16
|
+
expect(results).not_to be_empty
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
context "when not called with a block" do
|
|
20
20
|
it "should return an Enumerator" do
|
|
21
|
-
subject.scan.
|
|
21
|
+
expect(subject.scan).to be_kind_of(Enumerable)
|
|
22
22
|
end
|
|
23
23
|
end
|
|
24
24
|
end
|
|
@@ -31,9 +31,9 @@ describe Scanner do
|
|
|
31
31
|
subject { scanner.scan.to_a }
|
|
32
32
|
|
|
33
33
|
it "should match unpatched gems to their advisories" do
|
|
34
|
-
subject.all? { |result|
|
|
34
|
+
expect(subject.all? { |result|
|
|
35
35
|
result.advisory.vulnerable?(result.gem.version)
|
|
36
|
-
}.
|
|
36
|
+
}).to be_truthy
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
context "when the :ignore option is given" do
|
|
@@ -42,7 +42,7 @@ describe Scanner do
|
|
|
42
42
|
it "should ignore the specified advisories" do
|
|
43
43
|
ids = subject.map { |result| result.advisory.id }
|
|
44
44
|
|
|
45
|
-
ids.
|
|
45
|
+
expect(ids).not_to include('OSVDB-89026')
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
48
|
end
|
|
@@ -55,8 +55,8 @@ describe Scanner do
|
|
|
55
55
|
subject { scanner.scan.to_a }
|
|
56
56
|
|
|
57
57
|
it "should match unpatched gems to their advisories" do
|
|
58
|
-
subject[0].source.
|
|
59
|
-
subject[1].source.
|
|
58
|
+
expect(subject[0].source).to eq('git://github.com/rails/jquery-rails.git')
|
|
59
|
+
expect(subject[1].source).to eq('http://rubygems.org/')
|
|
60
60
|
end
|
|
61
61
|
end
|
|
62
62
|
|
|
@@ -68,7 +68,7 @@ describe Scanner do
|
|
|
68
68
|
subject { scanner.scan.to_a }
|
|
69
69
|
|
|
70
70
|
it "should print nothing when everything is fine" do
|
|
71
|
-
subject.
|
|
71
|
+
expect(subject).to be_empty
|
|
72
72
|
end
|
|
73
73
|
end
|
|
74
74
|
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
require 'simplecov'
|
|
2
|
+
SimpleCov.start
|
|
3
|
+
|
|
1
4
|
require 'rspec'
|
|
2
5
|
require 'bundler/audit/version'
|
|
3
6
|
|
|
@@ -19,15 +22,15 @@ module Helpers
|
|
|
19
22
|
end
|
|
20
23
|
|
|
21
24
|
def expect_update_to_clone_repo!
|
|
22
|
-
Bundler::Audit::Database.
|
|
23
|
-
|
|
25
|
+
expect(Bundler::Audit::Database).
|
|
26
|
+
to receive(:system).
|
|
24
27
|
with('git', 'clone', Bundler::Audit::Database::VENDORED_PATH, mocked_user_path).
|
|
25
28
|
and_call_original
|
|
26
29
|
end
|
|
27
30
|
|
|
28
31
|
def expect_update_to_update_repo!
|
|
29
|
-
Bundler::Audit::Database.
|
|
30
|
-
|
|
32
|
+
expect(Bundler::Audit::Database).
|
|
33
|
+
to receive(:system).
|
|
31
34
|
with('git', 'pull', 'origin', 'master').
|
|
32
35
|
and_call_original
|
|
33
36
|
end
|
metadata
CHANGED
|
@@ -1,41 +1,41 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bundler-audit
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Postmodern
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2015-06-30 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: thor
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
|
-
- - ~>
|
|
17
|
+
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
19
|
version: '0.18'
|
|
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
26
|
version: '0.18'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: bundler
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
|
-
- - ~>
|
|
31
|
+
- - "~>"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
33
|
version: '1.2'
|
|
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
40
|
version: '1.2'
|
|
41
41
|
description: bundler-audit provides patch-level verification for Bundled apps.
|
|
@@ -48,12 +48,12 @@ extra_rdoc_files:
|
|
|
48
48
|
- ChangeLog.md
|
|
49
49
|
- README.md
|
|
50
50
|
files:
|
|
51
|
-
- .document
|
|
52
|
-
- .gitignore
|
|
53
|
-
- .gitmodules
|
|
54
|
-
- .rspec
|
|
55
|
-
- .travis.yml
|
|
56
|
-
- .yardopts
|
|
51
|
+
- ".document"
|
|
52
|
+
- ".gitignore"
|
|
53
|
+
- ".gitmodules"
|
|
54
|
+
- ".rspec"
|
|
55
|
+
- ".travis.yml"
|
|
56
|
+
- ".yardopts"
|
|
57
57
|
- COPYING.txt
|
|
58
58
|
- ChangeLog.md
|
|
59
59
|
- Gemfile
|
|
@@ -62,23 +62,6 @@ files:
|
|
|
62
62
|
- bin/bundle-audit
|
|
63
63
|
- bundler-audit.gemspec
|
|
64
64
|
- data/ruby-advisory-db.ts
|
|
65
|
-
- gemspec.yml
|
|
66
|
-
- lib/bundler/audit.rb
|
|
67
|
-
- lib/bundler/audit/advisory.rb
|
|
68
|
-
- lib/bundler/audit/cli.rb
|
|
69
|
-
- lib/bundler/audit/database.rb
|
|
70
|
-
- lib/bundler/audit/scanner.rb
|
|
71
|
-
- lib/bundler/audit/version.rb
|
|
72
|
-
- spec/advisory_spec.rb
|
|
73
|
-
- spec/audit_spec.rb
|
|
74
|
-
- spec/bundle/insecure_sources/Gemfile
|
|
75
|
-
- spec/bundle/secure/Gemfile
|
|
76
|
-
- spec/bundle/unpatched_gems/Gemfile
|
|
77
|
-
- spec/database_spec.rb
|
|
78
|
-
- spec/fixtures/not_a_hash.yml
|
|
79
|
-
- spec/integration_spec.rb
|
|
80
|
-
- spec/scanner_spec.rb
|
|
81
|
-
- spec/spec_helper.rb
|
|
82
65
|
- data/ruby-advisory-db/.gitignore
|
|
83
66
|
- data/ruby-advisory-db/.rspec
|
|
84
67
|
- data/ruby-advisory-db/CONTRIBUTING.md
|
|
@@ -180,6 +163,23 @@ files:
|
|
|
180
163
|
- data/ruby-advisory-db/spec/advisory_example.rb
|
|
181
164
|
- data/ruby-advisory-db/spec/gems_spec.rb
|
|
182
165
|
- data/ruby-advisory-db/spec/spec_helper.rb
|
|
166
|
+
- gemspec.yml
|
|
167
|
+
- lib/bundler/audit.rb
|
|
168
|
+
- lib/bundler/audit/advisory.rb
|
|
169
|
+
- lib/bundler/audit/cli.rb
|
|
170
|
+
- lib/bundler/audit/database.rb
|
|
171
|
+
- lib/bundler/audit/scanner.rb
|
|
172
|
+
- lib/bundler/audit/version.rb
|
|
173
|
+
- spec/advisory_spec.rb
|
|
174
|
+
- spec/audit_spec.rb
|
|
175
|
+
- spec/bundle/insecure_sources/Gemfile
|
|
176
|
+
- spec/bundle/secure/Gemfile
|
|
177
|
+
- spec/bundle/unpatched_gems/Gemfile
|
|
178
|
+
- spec/database_spec.rb
|
|
179
|
+
- spec/fixtures/not_a_hash.yml
|
|
180
|
+
- spec/integration_spec.rb
|
|
181
|
+
- spec/scanner_spec.rb
|
|
182
|
+
- spec/spec_helper.rb
|
|
183
183
|
homepage: https://github.com/rubysec/bundler-audit#readme
|
|
184
184
|
licenses:
|
|
185
185
|
- GPLv3
|
|
@@ -190,17 +190,17 @@ require_paths:
|
|
|
190
190
|
- lib
|
|
191
191
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
192
192
|
requirements:
|
|
193
|
-
- -
|
|
193
|
+
- - ">="
|
|
194
194
|
- !ruby/object:Gem::Version
|
|
195
|
-
version:
|
|
195
|
+
version: 1.9.3
|
|
196
196
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
197
197
|
requirements:
|
|
198
|
-
- -
|
|
198
|
+
- - ">="
|
|
199
199
|
- !ruby/object:Gem::Version
|
|
200
200
|
version: 1.8.0
|
|
201
201
|
requirements: []
|
|
202
202
|
rubyforge_project:
|
|
203
|
-
rubygems_version: 2.
|
|
203
|
+
rubygems_version: 2.4.7
|
|
204
204
|
signing_key:
|
|
205
205
|
specification_version: 4
|
|
206
206
|
summary: Patch-level verification for Bundler
|