bundler-leak 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/.document +3 -0
  3. data/.gitignore +11 -0
  4. data/.gitmodules +3 -0
  5. data/.rspec +1 -0
  6. data/.travis.yml +13 -0
  7. data/.yardopts +1 -0
  8. data/COPYING.txt +674 -0
  9. data/ChangeLog.md +125 -0
  10. data/Gemfile +15 -0
  11. data/README.md +118 -0
  12. data/Rakefile +57 -0
  13. data/bin/bundle-leak +10 -0
  14. data/bin/bundler-leak +3 -0
  15. data/bundler-leak.gemspec +67 -0
  16. data/data/ruby-mem-advisory-db.ts +1 -0
  17. data/data/ruby-mem-advisory-db/.gitignore +1 -0
  18. data/data/ruby-mem-advisory-db/.rspec +1 -0
  19. data/data/ruby-mem-advisory-db/.travis.yml +12 -0
  20. data/data/ruby-mem-advisory-db/CONTRIBUTING.md +69 -0
  21. data/data/ruby-mem-advisory-db/CONTRIBUTORS.md +40 -0
  22. data/data/ruby-mem-advisory-db/Gemfile +9 -0
  23. data/data/ruby-mem-advisory-db/LICENSE.txt +5 -0
  24. data/data/ruby-mem-advisory-db/README.md +72 -0
  25. data/data/ruby-mem-advisory-db/Rakefile +26 -0
  26. data/data/ruby-mem-advisory-db/gems/celluloid/670.yml +10 -0
  27. data/data/ruby-mem-advisory-db/gems/grape/301.yml +9 -0
  28. data/data/ruby-mem-advisory-db/gems/oj/229.yml +9 -0
  29. data/data/ruby-mem-advisory-db/gems/redcarpet/516.yml +12 -0
  30. data/data/ruby-mem-advisory-db/gems/redis/612.yml +9 -0
  31. data/data/ruby-mem-advisory-db/gems/sidekiq-statistic/73.yml +9 -0
  32. data/data/ruby-mem-advisory-db/gems/sidekiq/2598.yml +9 -0
  33. data/data/ruby-mem-advisory-db/gems/therubyracer/336.yml +13 -0
  34. data/data/ruby-mem-advisory-db/gems/zipruby/PRE-SA-2012-02.yml +9 -0
  35. data/data/ruby-mem-advisory-db/scripts/post-advisories.sh +18 -0
  36. data/data/ruby-mem-advisory-db/spec/advisories_spec.rb +23 -0
  37. data/data/ruby-mem-advisory-db/spec/advisory_example.rb +209 -0
  38. data/data/ruby-mem-advisory-db/spec/gem_example.rb +37 -0
  39. data/data/ruby-mem-advisory-db/spec/library_example.rb +21 -0
  40. data/data/ruby-mem-advisory-db/spec/ruby_example.rb +22 -0
  41. data/data/ruby-mem-advisory-db/spec/spec_helper.rb +1 -0
  42. data/gemspec.yml +14 -0
  43. data/lib/bundler/plumber.rb +20 -0
  44. data/lib/bundler/plumber/advisory.rb +119 -0
  45. data/lib/bundler/plumber/cli.rb +135 -0
  46. data/lib/bundler/plumber/database.rb +249 -0
  47. data/lib/bundler/plumber/scanner.rb +133 -0
  48. data/lib/bundler/plumber/task.rb +49 -0
  49. data/lib/bundler/plumber/version.rb +24 -0
  50. data/spec/advisory_spec.rb +155 -0
  51. data/spec/audit_spec.rb +8 -0
  52. data/spec/bundle/insecure_sources/Gemfile +39 -0
  53. data/spec/bundle/secure/Gemfile +38 -0
  54. data/spec/bundle/unpatched_gems/Gemfile +39 -0
  55. data/spec/cli_spec.rb +99 -0
  56. data/spec/database_spec.rb +138 -0
  57. data/spec/fixtures/not_a_hash.yml +2 -0
  58. data/spec/integration_spec.rb +68 -0
  59. data/spec/scanner_spec.rb +61 -0
  60. data/spec/spec_helper.rb +62 -0
  61. metadata +141 -0
@@ -0,0 +1,133 @@
1
+ #
2
+ # Copyright (c) 2019 Ombulabs (hello at ombulabs.com)
3
+ # Copyright (c) 2013-2016 Hal Brodigan (postmodern.mod3 at gmail.com)
4
+ #
5
+ # bundler-leak is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # bundler-leak is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with bundler-leak. If not, see <http://www.gnu.org/licenses/>.
17
+ #
18
+
19
+ require 'bundler'
20
+ require 'bundler/plumber/database'
21
+ require 'bundler/lockfile_parser'
22
+
23
+ require 'ipaddr'
24
+ require 'resolv'
25
+ require 'set'
26
+ require 'uri'
27
+
28
+ module Bundler
29
+ module Plumber
30
+ class Scanner
31
+
32
+ # Represents a gem that is covered by an Advisory
33
+ UnpatchedGem = Struct.new(:gem, :advisory)
34
+
35
+ # The advisory database
36
+ #
37
+ # @return [Database]
38
+ attr_reader :database
39
+
40
+ # Project root directory
41
+ attr_reader :root
42
+
43
+ # The parsed `Gemfile.lock` from the project
44
+ #
45
+ # @return [Bundler::LockfileParser]
46
+ attr_reader :lockfile
47
+
48
+ #
49
+ # Initializes a scanner.
50
+ #
51
+ # @param [String] root
52
+ # The path to the project root.
53
+ #
54
+ # @param [String] gemfile_lock
55
+ # Alternative name for the `Gemfile.lock` file.
56
+ #
57
+ def initialize(root=Dir.pwd,gemfile_lock='Gemfile.lock')
58
+ @root = File.expand_path(root)
59
+ @database = Database.new
60
+ @lockfile = LockfileParser.new(
61
+ File.read(File.join(@root,gemfile_lock))
62
+ )
63
+ end
64
+
65
+ #
66
+ # Scans the project for issues.
67
+ #
68
+ # @param [Hash] options
69
+ # Additional options.
70
+ #
71
+ # @option options [Array<String>] :ignore
72
+ # The advisories to ignore.
73
+ #
74
+ # @yield [result]
75
+ # The given block will be passed the results of the scan.
76
+ #
77
+ # @return [Enumerator]
78
+ # If no block is given, an Enumerator will be returned.
79
+ #
80
+ def scan(options={},&block)
81
+ return enum_for(__method__, options) unless block
82
+
83
+ ignore = Set[]
84
+ ignore += options[:ignore] if options[:ignore]
85
+
86
+ scan_specs(options, &block)
87
+
88
+ return self
89
+ end
90
+
91
+ #
92
+ # Scans the gem sources in the lockfile.
93
+ #
94
+ # @param [Hash] options
95
+ # Additional options.
96
+ #
97
+ # @option options [Array<String>] :ignore
98
+ # The advisories to ignore.
99
+ #
100
+ # @yield [result]
101
+ # The given block will be passed the results of the scan.
102
+ #
103
+ # @yieldparam [UnpatchedGem] result
104
+ # A result from the scan.
105
+ #
106
+ # @return [Enumerator]
107
+ # If no block is given, an Enumerator will be returned.
108
+ #
109
+ # @api semipublic
110
+ #
111
+ # @since 0.4.0
112
+ #
113
+ def scan_specs(options={})
114
+ return enum_for(__method__, options) unless block_given?
115
+
116
+ ignore = Set[]
117
+ ignore += options[:ignore] if options[:ignore]
118
+
119
+ @lockfile.specs.each do |gem|
120
+ @database.check_gem(gem) do |advisory|
121
+
122
+ # TODO this logic should be modified for rubymem
123
+ #unless (ignore.include?(advisory.cve_id) || ignore.include?(advisory.osvdb_id))
124
+ # yield UnpatchedGem.new(gem,advisory)
125
+ #end
126
+ yield UnpatchedGem.new(gem, advisory)
127
+ end
128
+ end
129
+ end
130
+
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,49 @@
1
+ #
2
+ # Copyright (c) 2019 Ombulabs (hello at ombulabs.com)
3
+ # Copyright (c) 2013-2016 Hal Brodigan (postmodern.mod3 at gmail.com)
4
+ #
5
+ # bundler-leak is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # bundler-leak is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with bundler-leak. If not, see <http://www.gnu.org/licenses/>.
17
+ #
18
+
19
+ require 'rake/tasklib'
20
+
21
+ module Bundler
22
+ module Plumber
23
+ class Task < Rake::TaskLib
24
+ #
25
+ # Initializes the task.
26
+ #
27
+ def initialize
28
+ define
29
+ end
30
+
31
+ protected
32
+
33
+ #
34
+ # Defines the `bundle:leak` task.
35
+ #
36
+ def define
37
+ namespace :bundle do
38
+ desc 'Updates the ruby-mem-advisory-db then runs bundle-leak'
39
+ task :leak do
40
+ require 'bundler/plumber/cli'
41
+ %w(update check).each do |command|
42
+ Bundler::Plumber::CLI.start [command]
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,24 @@
1
+ #
2
+ # Copyright (c) 2019 Ombulabs (hello at ombulabs.com)
3
+ # Copyright (c) 2019 Ombulabs (hello at ombulabs.com)
4
+ #
5
+ # bundler-leak is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # bundler-leak is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with bundler-leak. If not, see <http://www.gnu.org/licenses/>.
17
+ #
18
+
19
+ module Bundler
20
+ module Plumber
21
+ # bundler-leak version
22
+ VERSION = '0.0.0'
23
+ end
24
+ end
@@ -0,0 +1,155 @@
1
+ require 'spec_helper'
2
+ require 'bundler/plumber/database'
3
+ require 'bundler/plumber/advisory'
4
+
5
+ describe Bundler::Plumber::Advisory do
6
+ let(:root) { Bundler::Plumber::Database::VENDORED_PATH }
7
+ let(:gem) { 'therubyracer' }
8
+ let(:id) { '336' }
9
+ let(:path) { File.join(root,'gems',gem,"#{id}.yml") }
10
+ let(:an_unaffected_version) do
11
+ Bundler::Plumber::Advisory.load(path).unaffected_versions.map { |version_rule|
12
+ # For all the rules, get the individual constraints out and see if we
13
+ # can find a suitable one...
14
+ version_rule.requirements.select { |(constraint, gem_version)|
15
+ # We only want constraints where the version number specified is
16
+ # one of the unaffected version. I.E. we don't want ">", "<", or if
17
+ # such a thing exists, "!=" constraints.
18
+ ['~>', '>=', '=', '<='].include?(constraint)
19
+ }.map { |(constraint, gem_version)|
20
+ # Fetch just the version component, which is a Gem::Version,
21
+ # and extract the string representation of the version.
22
+ gem_version.version
23
+ }
24
+ }.flatten.first
25
+ end
26
+
27
+ subject { described_class.load(path) }
28
+
29
+ describe "load" do
30
+ let(:data) { YAML.load_file(path) }
31
+
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 '#date' do
48
+ subject { super().date }
49
+ it { is_expected.to eq(data['date']) }
50
+ end
51
+
52
+ describe '#description' do
53
+ subject { super().description }
54
+ it { is_expected.to eq(data['description']) }
55
+ end
56
+
57
+ context "YAML data not representing a hash" do
58
+ it "should raise an exception" do
59
+ path = File.expand_path('../fixtures/not_a_hash.yml', __FILE__)
60
+ expect {
61
+ Advisory.load(path)
62
+ }.to raise_exception("advisory data in #{path.dump} was not a Hash")
63
+ end
64
+ end
65
+
66
+ describe "#patched_versions" do
67
+ subject { described_class.load(path).patched_versions }
68
+
69
+ it "should all be Gem::Requirement objects" do
70
+ expect(subject.all? { |version|
71
+ expect(version).to be_kind_of(Gem::Requirement)
72
+ }).to be_truthy
73
+ end
74
+
75
+ it "should parse the versions" do
76
+ expect(subject.map(&:to_s)).to eq(data['patched_versions'])
77
+ end
78
+ end
79
+ end
80
+
81
+
82
+ describe "#unaffected?" do
83
+ context "when passed a version that matches one unaffected version" do
84
+ let(:version) { Gem::Version.new(an_unaffected_version) }
85
+
86
+ it "should return true" do
87
+ expect(subject.unaffected?(version)).to be_truthy
88
+ end
89
+ end
90
+
91
+ context "when passed a version that matches no unaffected version" do
92
+ let(:version) { Gem::Version.new('3.0.9') }
93
+
94
+ it "should return false" do
95
+ expect(subject.unaffected?(version)).to be_falsey
96
+ end
97
+ end
98
+ end
99
+
100
+ describe "#patched?" do
101
+ context "when passed a version that matches one patched version" do
102
+ let(:version) { Gem::Version.new('0.12.4') }
103
+
104
+ it "should return true", doku: true do
105
+ expect(subject.patched?(version)).to be_truthy
106
+ end
107
+ end
108
+
109
+ context "when passed a version that matches no patched version" do
110
+ let(:version) { Gem::Version.new('2.9.0') }
111
+
112
+ it "should return false" do
113
+ expect(subject.patched?(version)).to be_falsey
114
+ end
115
+ end
116
+ end
117
+
118
+ describe "#vulnerable?" do
119
+ context "when passed a version that matches one patched version" do
120
+ let(:version) { Gem::Version.new('0.12.4') }
121
+
122
+ it "should return false" do
123
+ expect(subject.vulnerable?(version)).to be_falsey
124
+ end
125
+ end
126
+
127
+ context "when passed a version that matches no patched version" do
128
+ let(:version) { Gem::Version.new('2.9.0') }
129
+
130
+ it "should return true" do
131
+ expect(subject.vulnerable?(version)).to be_truthy
132
+ end
133
+
134
+ context "when unaffected_versions is not empty" do
135
+ subject { described_class.load(path) }
136
+
137
+ context "when passed a version that matches one unaffected version" do
138
+ let(:version) { Gem::Version.new(an_unaffected_version) }
139
+
140
+ it "should return false" do
141
+ expect(subject.vulnerable?(version)).to be_falsey
142
+ end
143
+ end
144
+
145
+ context "when passed a version that matches no unaffected version" do
146
+ let(:version) { Gem::Version.new('1.2.3') }
147
+
148
+ it "should return true" do
149
+ expect(subject.vulnerable?(version)).to be_truthy
150
+ end
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+ require 'bundler/plumber'
3
+
4
+ describe Bundler::Plumber do
5
+ it "should have a VERSION constant" do
6
+ expect(subject.const_get('VERSION')).not_to be_empty
7
+ end
8
+ end
@@ -0,0 +1,39 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'rails', '3.2.12'
4
+
5
+ # Bundle edge Rails instead:
6
+ # gem 'rails', :git => 'git://github.com/rails/rails.git'
7
+
8
+ gem 'sqlite3', platform: [:mri, :rbx]
9
+
10
+
11
+ # Gems used only for assets and not required
12
+ # in production environments by default.
13
+ group :assets do
14
+ # gem 'sass-rails', '~> 3.2.3'
15
+ # gem 'coffee-rails', '~> 3.2.1'
16
+
17
+ # See https://github.com/sstephenson/execjs#readme for more supported runtimes
18
+ # gem 'therubyracer', :platforms => :ruby
19
+
20
+ # gem 'uglifier', '>= 1.0.3'
21
+ end
22
+
23
+ gem 'jquery-rails', :git => 'git://github.com/rails/jquery-rails.git',
24
+ :tag => 'v2.2.1'
25
+
26
+ # To use ActiveModel has_secure_password
27
+ # gem 'bcrypt-ruby', '~> 3.0.0'
28
+
29
+ # To use Jbuilder templates for JSON
30
+ # gem 'jbuilder'
31
+
32
+ # Use unicorn as the app server
33
+ # gem 'unicorn'
34
+
35
+ # Deploy with Capistrano
36
+ # gem 'capistrano'
37
+
38
+ # To use debugger
39
+ # gem 'debugger'
@@ -0,0 +1,38 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'rails', '~> 4.2.7.1'
4
+
5
+ # Bundle edge Rails instead:
6
+ # gem 'rails', :git => 'git://github.com/rails/rails.git'
7
+
8
+ gem 'sqlite3', platform: [:mri, :rbx]
9
+
10
+
11
+ # Gems used only for assets and not required
12
+ # in production environments by default.
13
+ group :assets do
14
+ # gem 'sass-rails', '~> 3.2.3'
15
+ # gem 'coffee-rails', '~> 3.2.1'
16
+
17
+ # See https://github.com/sstephenson/execjs#readme for more supported runtimes
18
+ # gem 'therubyracer', :platforms => :ruby
19
+
20
+ # gem 'uglifier', '>= 1.0.3'
21
+ end
22
+
23
+ gem 'jquery-rails'
24
+
25
+ # To use ActiveModel has_secure_password
26
+ # gem 'bcrypt-ruby', '~> 3.0.0'
27
+
28
+ # To use Jbuilder templates for JSON
29
+ # gem 'jbuilder'
30
+
31
+ # Use unicorn as the app server
32
+ # gem 'unicorn'
33
+
34
+ # Deploy with Capistrano
35
+ # gem 'capistrano'
36
+
37
+ # To use debugger
38
+ # gem 'debugger'