bundler-organization_audit 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Binary file
@@ -0,0 +1 @@
1
+ spec/private.yml
@@ -0,0 +1,4 @@
1
+ rvm:
2
+ - ree
3
+ - 1.9.2
4
+ - 1.9.3
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source :rubygems
2
+ gemspec
3
+
4
+ gem "bump"
5
+ gem "rake"
6
+ gem "rspec", "~>2"
7
+ gem "bundler-audit"
@@ -0,0 +1,33 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ bundler-organization_audit (0.1.0)
5
+ json
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ bump (0.3.9)
11
+ bundler-audit (0.1.2)
12
+ bundler (~> 1.2)
13
+ diff-lcs (1.1.3)
14
+ json (1.7.7)
15
+ rake (10.0.3)
16
+ rspec (2.12.0)
17
+ rspec-core (~> 2.12.0)
18
+ rspec-expectations (~> 2.12.0)
19
+ rspec-mocks (~> 2.12.0)
20
+ rspec-core (2.12.2)
21
+ rspec-expectations (2.12.1)
22
+ diff-lcs (~> 1.1.3)
23
+ rspec-mocks (2.12.2)
24
+
25
+ PLATFORMS
26
+ ruby
27
+
28
+ DEPENDENCIES
29
+ bump
30
+ bundler-audit
31
+ bundler-organization_audit!
32
+ rake
33
+ rspec (~> 2)
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "bump/tasks"
3
+
4
+ task :default do
5
+ sh "rspec spec/"
6
+ end
@@ -0,0 +1,76 @@
1
+ Audit all Gemfiles of a user/organization on Github for unpatched versions
2
+
3
+ gem install bundler-organization_audit
4
+
5
+ Usage
6
+ =====
7
+
8
+ ### Public repos
9
+ For yourself (git config github.user)
10
+ ```Bash
11
+ bundle-organization-audit
12
+ parallel
13
+ No Gemfile.lock found
14
+
15
+ parllel_tests
16
+ bundle-audit
17
+ No unpatched versions found
18
+
19
+ rails_example_app
20
+ bundle-audit
21
+ Name: rack
22
+ Version: 1.4.4
23
+ CVE: 2013-0263
24
+ Criticality: High
25
+ URL: http://osvdb.org/show/osvdb/89939
26
+ Title: Rack Rack::Session::Cookie Function Timing Attack Remote Code Execution
27
+ Patched Versions: ~> 1.1.6, ~> 1.2.8, ~> 1.3.10, ~> 1.4.5, >= 1.5.2
28
+
29
+ Vulnerable:
30
+ https://github.com/grosser/rails_example_app
31
+ ```
32
+
33
+ For someone elese
34
+ ```Bash
35
+ bundle-organization-audit --user grosser
36
+ ```
37
+
38
+ Ignore gems (ignores repos that have a %{repo}.gemspec)
39
+ ```Bash
40
+ bundle-organization-audit --ignore-gems
41
+ ```
42
+
43
+ For pipe -> only show vulnerable repos
44
+ ```
45
+ bundle-organization-audit 2>/dev/null
46
+ ```
47
+
48
+ Use for CI -> ignore old/unmaintained proejcts
49
+ ```
50
+ bundle-organization-audit \
51
+ --ignore https://github.com/xxx/a \
52
+ --ignore https://github.com/xxx/b \
53
+ --organization xxx \
54
+ --token yyy
55
+ ```
56
+
57
+ ### Private repos
58
+
59
+ ```Bash
60
+ # create a token that has access to your repositories
61
+ curl -v -u your-user-name -X POST https://api.github.com/authorizations --data '{"scopes":["repo"]}'
62
+ enter your password -> TOKEN
63
+
64
+ bundle-organization-audit --user your-user --token TOKEN --organization your-organization
65
+ ```
66
+
67
+ Dev
68
+ ===
69
+ - test private repo fetching via `cp spec/private{.example,}.yml` and filling it out
70
+
71
+ Author
72
+ ======
73
+ [Michael Grosser](http://grosser.it)<br/>
74
+ michael@grosser.it<br/>
75
+ License: MIT<br/>
76
+ [![Build Status](https://travis-ci.org/grosser/bundler-organization_audit.png)](https://travis-ci.org/grosser/bundler-organization_audit)
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env ruby
2
+ require "rubygems"
3
+ require "optparse"
4
+
5
+ $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
6
+ require "bundler/organization_audit"
7
+
8
+ def git_config(thing)
9
+ result = `git config #{thing}`.strip
10
+ result.empty? ? nil : result
11
+ end
12
+
13
+ options = {
14
+ :ignore => [],
15
+ :user => git_config("github.user")
16
+ }
17
+ OptionParser.new do |opts|
18
+ opts.banner = <<BANNER
19
+ Audit all Gemfiles of a user/organization on github for unpatched versions
20
+
21
+ Usage:
22
+ bundle-organization-audit your-user-name
23
+
24
+ Options:
25
+ BANNER
26
+ opts.on("--token TOKEN", "Use token") { |token| options[:token] = token }
27
+ opts.on("--user USER", "Use user") { |user| options[:user] = user }
28
+ opts.on("--ignore REPO_URL", "Ignore given repo urls (use multiple times)") { |repo_url| options[:ignore] << repo_url }
29
+ opts.on("--ignore-gems", "Ignore repos that have a %{repo}.gemspec") { options[:ignore_gems] = true }
30
+ opts.on("--organization ORGANIZATION", "Use user") { |organization| options[:organization] = organization }
31
+ opts.on("-h", "--help", "Show this.") { puts opts; exit }
32
+ opts.on("-v", "--version", "Show Version"){ puts Bundler::OrganizationAudit::VERSION; exit}
33
+ end.parse!
34
+
35
+ exit Bundler::OrganizationAudit.run(options)
@@ -0,0 +1,16 @@
1
+ $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
2
+ name = "bundler-organization_audit"
3
+ require "#{name.gsub("-","/")}/version"
4
+
5
+ Gem::Specification.new name, Bundler::OrganizationAudit::VERSION do |s|
6
+ s.summary = s.description = "Audit all Gemfiles of a user/organization on github for unpatched versions"
7
+ s.authors = ["Michael Grosser"]
8
+ s.email = "michael@grosser.it"
9
+ s.homepage = "http://github.com/grosser/#{name}"
10
+ s.files = `git ls-files`.split("\n")
11
+ s.license = "MIT"
12
+ s.signing_key = File.expand_path("~/.ssh/gem-private_key.pem")
13
+ s.executables = ["bundle-organization-audit"]
14
+ s.cert_chain = ["gem-public_cert.pem"]
15
+ s.add_runtime_dependency "json"
16
+ end
@@ -0,0 +1,20 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDMjCCAhqgAwIBAgIBADANBgkqhkiG9w0BAQUFADA/MRAwDgYDVQQDDAdtaWNo
3
+ YWVsMRcwFQYKCZImiZPyLGQBGRYHZ3Jvc3NlcjESMBAGCgmSJomT8ixkARkWAml0
4
+ MB4XDTEzMDIwMzE4MTMxMVoXDTE0MDIwMzE4MTMxMVowPzEQMA4GA1UEAwwHbWlj
5
+ aGFlbDEXMBUGCgmSJomT8ixkARkWB2dyb3NzZXIxEjAQBgoJkiaJk/IsZAEZFgJp
6
+ dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMorXo/hgbUq97+kII9H
7
+ MsQcLdC/7wQ1ZP2OshVHPkeP0qH8MBHGg6eYisOX2ubNagF9YTCZWnhrdKrwpLOO
8
+ cPLaZbjUjljJ3cQR3B8Yn1veV5IhG86QseTBjymzJWsLpqJ1UZGpfB9tXcsFtuxO
9
+ 6vHvcIHdzvc/OUkICttLbH+1qb6rsHUceqh+JrH4GrsJ5H4hAfIdyS2XMK7YRKbh
10
+ h+IBu6dFWJJByzFsYmV1PDXln3UBmgAt65cmCu4qPfThioCGDzbSJrGDGLmw/pFX
11
+ FPpVCm1zgYSb1v6Qnf3cgXa2f2wYGm17+zAVyIDpwryFru9yF/jJxE38z/DRsd9R
12
+ /88CAwEAAaM5MDcwCQYDVR0TBAIwADAdBgNVHQ4EFgQUsiNnXHtKeMYYcr4yJVmQ
13
+ WONL+IwwCwYDVR0PBAQDAgSwMA0GCSqGSIb3DQEBBQUAA4IBAQAlyN7kKo/NQCQ0
14
+ AOzZLZ3WAePvStkCFIJ53tsv5Kyo4pMAllv+BgPzzBt7qi605mFSL6zBd9uLou+W
15
+ Co3s48p1dy7CjjAfVQdmVNHF3MwXtfC2OEyvSQPi4xKR8iba8wa3xp9LVo1PuLpw
16
+ /6DsrChWw74HfsJN6qJOK684hJeT8lBYAUfiC3wD0owoPSg+XtyAAddisR+KV5Y1
17
+ NmVHuLtQcNTZy+gRht3ahJRMuC6QyLmkTsf+6MaenwAMkAgHdswGsJztOnNnBa3F
18
+ y0kCSWmK6D+x/SbfS6r7Ke07MRqziJdB9GuE1+0cIRuFh8EQ+LN6HXCKM5pon/GU
19
+ ycwMXfl0
20
+ -----END CERTIFICATE-----
@@ -0,0 +1,68 @@
1
+ require "bundler/organization_audit/version"
2
+ require "tmpdir"
3
+ require "bundler/organization_audit/repo"
4
+
5
+ module Bundler
6
+ module OrganizationAudit
7
+ class << self
8
+ def run(options)
9
+ vulnerable = find_vulnerable(options).map(&:url)
10
+ vulnerable -= (options[:ignore] || [])
11
+ if vulnerable.size == 0
12
+ 0
13
+ else
14
+ $stderr.puts "Vulnerable:"
15
+ puts vulnerable
16
+ 1
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def download_file(repo, file, options)
23
+ return unless content = repo.content(file, options)
24
+ File.open(file, "w") { |f| f.write content }
25
+ end
26
+
27
+ def find_vulnerable(options)
28
+ Repo.all(options).select do |repo|
29
+ audit_repo(repo, options)
30
+ end
31
+ end
32
+
33
+ def audit_repo(repo, options)
34
+ success = false
35
+ $stderr.puts repo.project
36
+ in_temp_dir do
37
+ if download_file(repo, "Gemfile.lock", options)
38
+ if options[:ignore_gems] && repo.gem?(options)
39
+ $stderr.puts "Ignored because it's a gem"
40
+ else
41
+ success = !sh("bundle-audit")
42
+ end
43
+ else
44
+ $stderr.puts "No Gemfile.lock found"
45
+ end
46
+ end
47
+ $stderr.puts ""
48
+ success
49
+ rescue Exception => e
50
+ $stderr.puts "Error auditing #{repo.project} (#{e})"
51
+ end
52
+
53
+ def in_temp_dir(&block)
54
+ Dir.mktmpdir { |dir| Dir.chdir(dir, &block) }
55
+ end
56
+
57
+ def sh(cmd)
58
+ $stderr.puts cmd
59
+ IO.popen(cmd) do |pipe|
60
+ while str = pipe.gets
61
+ $stderr.puts str
62
+ end
63
+ end
64
+ $?.success?
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,101 @@
1
+ require "open-uri"
2
+ require "json"
3
+ require "base64"
4
+
5
+ module Bundler
6
+ module OrganizationAudit
7
+ class Repo
8
+ HOST = "https://api.github.com"
9
+
10
+ def initialize(data)
11
+ @data = data
12
+ end
13
+
14
+ def gem?(options={})
15
+ !!content("#{project}.gemspec", options)
16
+ end
17
+
18
+ def url
19
+ api_url.sub("api.", "").sub("/repos", "")
20
+ end
21
+ alias_method :to_s, :url
22
+
23
+ def project
24
+ api_url.split("/").last
25
+ end
26
+
27
+ def self.all(options)
28
+ user = if options[:organization]
29
+ "orgs/#{options[:organization]}"
30
+ elsif options[:user]
31
+ "users/#{options[:user]}"
32
+ else
33
+ "user"
34
+ end
35
+ url = File.join(HOST, user, "repos")
36
+
37
+ download_all_pages(url, headers(options[:token])).map { |data| Repo.new(data) }
38
+ end
39
+
40
+ def content(file, options={})
41
+ if private?
42
+ download_content_via_api(file, options)
43
+ else
44
+ download_content_via_raw(file)
45
+ end
46
+ rescue OpenURI::HTTPError => e
47
+ raise "Error downloading #{file} from #{url} (#{e})" unless e.message.start_with?("404")
48
+ end
49
+
50
+ def private?
51
+ @data["private"]
52
+ end
53
+
54
+ private
55
+
56
+ def self.download_all_pages(url, headers)
57
+ results = []
58
+ page = 1
59
+ loop do
60
+ result = JSON.parse(open("#{url}?page=#{page}", headers).read)
61
+ if result.size == 0
62
+ break
63
+ else
64
+ results.concat(result)
65
+ page += 1
66
+ end
67
+ end
68
+ results
69
+ end
70
+
71
+ def branch
72
+ @data["default_branch"] || @data["master_branch"] || "master"
73
+ end
74
+
75
+ def api_url
76
+ @data["url"]
77
+ end
78
+
79
+ def raw_url
80
+ url.sub("://", "://raw.")
81
+ end
82
+
83
+ # increases api rate limit
84
+ def download_content_via_api(file, options)
85
+ url = File.join(api_url, "contents", file, "?ref=#{branch}")
86
+ content = open(url, self.class.headers(options.fetch(:token))).read
87
+ content = JSON.load(content)["content"]
88
+ Base64.decode64(content)
89
+ end
90
+
91
+ # unlimited
92
+ def download_content_via_raw(file)
93
+ open(File.join(raw_url, branch, file)).read
94
+ end
95
+
96
+ def self.headers(token)
97
+ token ? {"Authorization" => "token #{token}"} : {}
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,5 @@
1
+ module Bundler
2
+ module OrganizationAudit
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,58 @@
1
+ require "spec_helper"
2
+
3
+ describe Bundler::OrganizationAudit::Repo do
4
+ let(:config){ YAML.load_file("spec/private.yml") }
5
+ let(:repo) do
6
+ Bundler::OrganizationAudit::Repo.new(
7
+ "url" => "https://api.github.com/repos/grosser/parallel"
8
+ )
9
+ end
10
+
11
+ describe ".all" do
12
+ it "returns the list of public repositories" do
13
+ # use a big account -> make sure pagination works
14
+ list = Bundler::OrganizationAudit::Repo.all(:user => "grosser")
15
+ list.map(&:url).should include("https://github.com/grosser/parallel")
16
+ end
17
+
18
+ if File.exist?("spec/private.yml")
19
+ it "returns the list of private repositories from a user" do
20
+ list = Bundler::OrganizationAudit::Repo.all(:token => config["token"])
21
+ list.map(&:url).should include("https://github.com/#{config["user"]}/#{config["expected_user"]}")
22
+ end
23
+
24
+ it "returns the list of private repositories from a organization" do
25
+ list = Bundler::OrganizationAudit::Repo.all(:token => config["token"], :organization => config["organization"])
26
+ list.map(&:url).should include("https://github.com/#{config["organization"]}/#{config["expected_organization"]}")
27
+ end
28
+ end
29
+ end
30
+
31
+ describe "#content" do
32
+ it "can download a public file" do
33
+ repo.content("Gemfile.lock").should include('rspec (2')
34
+ end
35
+
36
+ if File.exist?("spec/private.yml")
37
+ it "can download a private file" do
38
+ url = "https://api.github.com/repos/#{config["organization"]}/#{config["expected_organization"]}"
39
+ repo = Bundler::OrganizationAudit::Repo.new(
40
+ "url" => url, "private" => true
41
+ )
42
+ content = repo.content("Gemfile.lock", :token => config["token"], :user => config["user"])
43
+ content.should include('i18n (0.')
44
+ end
45
+ end
46
+ end
47
+
48
+ describe "#gem?" do
49
+ it "is a gem if it has a gemspec" do
50
+ repo.should be_gem
51
+ end
52
+
53
+ it "is not a gem if it has no gemspec" do
54
+ Bundler::OrganizationAudit::Repo.new("url" => "https://api.github.com/repos/grosser/dotfiles").should_not be_gem
55
+ end
56
+ end
57
+ end
58
+
@@ -0,0 +1,112 @@
1
+ require "spec_helper"
2
+
3
+ describe Bundler::OrganizationAudit do
4
+ it "has a VERSION" do
5
+ Bundler::OrganizationAudit::VERSION.should =~ /^[\.\da-z]+$/
6
+ end
7
+
8
+ describe Bundler::OrganizationAudit do
9
+ let(:repo) do
10
+ Bundler::OrganizationAudit::Repo.new(
11
+ "url" => "https://api.github.com/repos/grosser/parallel"
12
+ )
13
+ end
14
+
15
+ describe ".audit_repo" do
16
+ it "audits public repos" do
17
+ out = record_out do
18
+ Bundler::OrganizationAudit.send(:audit_repo, repo, {})
19
+ end
20
+ out.strip.should == "parallel\nbundle-audit\nNo unpatched versions found"
21
+ end
22
+
23
+ it "does not audit ignored repos" do
24
+ out = record_out do
25
+ Bundler::OrganizationAudit.send(:audit_repo, repo, :ignore_gems => true)
26
+ end
27
+ out.strip.should == "parallel\nIgnored because it's a gem"
28
+ end
29
+ end
30
+
31
+ describe ".run" do
32
+ before do
33
+ Bundler::OrganizationAudit.stub(:puts)
34
+ end
35
+
36
+ it "is successful when failed are empty" do
37
+ Bundler::OrganizationAudit.should_receive(:find_vulnerable).and_return([])
38
+ record_out do
39
+ Bundler::OrganizationAudit.run({}).should == 0
40
+ end
41
+ end
42
+
43
+ it "fails with failed" do
44
+ Bundler::OrganizationAudit.should_receive(:find_vulnerable).and_return([repo])
45
+ record_out do
46
+ Bundler::OrganizationAudit.run({}).should == 1
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ context "CLI" do
53
+ it "can audit a user" do
54
+ result = audit("--user anamartinez")
55
+ result.should include "I18N-tools\nNo Gemfile.lock found" # did not use audit when not necessary
56
+ result.should include "js-cldr-timezones\nbundle-audit\nNo unpatched versions found" # used audit where necessary
57
+ end
58
+
59
+ it "can audit a unpatched user" do
60
+ result = audit("--user user-with-unpatched-apps", :fail => true)
61
+ result.should include "unpatched\nbundle-audit\nName: json\nVersion: 1.5.3" # Individual vulnerabilities
62
+ result.should include "Vulnerable:\nhttps://github.com/user-with-unpatched-apps/unpatched" # Summary
63
+ end
64
+
65
+ it "only shows failed projects on stdout" do
66
+ result = audit("--user user-with-unpatched-apps 2>/dev/null", :fail => true, :keep_output => true)
67
+ result.should == "https://github.com/user-with-unpatched-apps/unpatched\n"
68
+ end
69
+
70
+ it "ignores projects in --ignore" do
71
+ result = audit("--user user-with-unpatched-apps --ignore https://github.com/user-with-unpatched-apps/unpatched 2>/dev/null", :keep_output => true)
72
+ result.should == ""
73
+ end
74
+
75
+ it "shows --version" do
76
+ audit("--version").should include(Bundler::OrganizationAudit::VERSION)
77
+ end
78
+
79
+ it "shows --help" do
80
+ audit("--help").should include("Audit all Gemfiles")
81
+ end
82
+
83
+ def audit(command, options={})
84
+ sh("bin/bundle-organization-audit #{command}", options)
85
+ end
86
+
87
+ def sh(command, options={})
88
+ result = `#{command} #{"2>&1" unless options[:keep_output]}`
89
+ raise "FAILED #{command}\n#{result}" if $?.success? == !!options[:fail]
90
+ decolorize(result)
91
+ end
92
+ end
93
+
94
+ def decolorize(string)
95
+ string.gsub(/\e\[\d+m/, "")
96
+ end
97
+
98
+ def record_out
99
+ recorder = StringIO.new
100
+ $stdout, out = recorder, $stdout
101
+ $stderr, err = recorder, $stderr
102
+ yield
103
+ decolorize(recorder.string)
104
+ ensure
105
+ $stdout = out
106
+ $stderr = err
107
+ end
108
+
109
+ def in_temp_dir(&block)
110
+ Dir.mktmpdir { |dir| Dir.chdir(dir, &block) }
111
+ end
112
+ end
@@ -0,0 +1,7 @@
1
+ token: your-token-see-readme
2
+
3
+ user: your-user
4
+ expected_user: your-private-repo
5
+
6
+ organization: org
7
+ expected_organization: org-private-repo
@@ -0,0 +1 @@
1
+ require "bundler/organization_audit"
metadata ADDED
@@ -0,0 +1,111 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bundler-organization_audit
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Michael Grosser
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain:
12
+ - !binary |-
13
+ LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURNakNDQWhxZ0F3SUJB
14
+ Z0lCQURBTkJna3Foa2lHOXcwQkFRVUZBREEvTVJBd0RnWURWUVFEREFkdGFX
15
+ Tm8KWVdWc01SY3dGUVlLQ1pJbWlaUHlMR1FCR1JZSFozSnZjM05sY2pFU01C
16
+ QUdDZ21TSm9tVDhpeGtBUmtXQW1sMApNQjRYRFRFek1ESXdNekU0TVRNeE1W
17
+ b1hEVEUwTURJd016RTRNVE14TVZvd1B6RVFNQTRHQTFVRUF3d0hiV2xqCmFH
18
+ RmxiREVYTUJVR0NnbVNKb21UOGl4a0FSa1dCMmR5YjNOelpYSXhFakFRQmdv
19
+ SmtpYUprL0lzWkFFWkZnSnAKZERDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFB
20
+ RGdnRVBBRENDQVFvQ2dnRUJBTW9yWG8vaGdiVXE5NytrSUk5SApNc1FjTGRD
21
+ Lzd3UTFaUDJPc2hWSFBrZVAwcUg4TUJIR2c2ZVlpc09YMnViTmFnRjlZVENa
22
+ V25ocmRLcndwTE9PCmNQTGFaYmpVamxqSjNjUVIzQjhZbjF2ZVY1SWhHODZR
23
+ c2VUQmp5bXpKV3NMcHFKMVVaR3BmQjl0WGNzRnR1eE8KNnZIdmNJSGR6dmMv
24
+ T1VrSUN0dExiSCsxcWI2cnNIVWNlcWgrSnJINEdyc0o1SDRoQWZJZHlTMlhN
25
+ SzdZUktiaApoK0lCdTZkRldKSkJ5ekZzWW1WMVBEWGxuM1VCbWdBdDY1Y21D
26
+ dTRxUGZUaGlvQ0dEemJTSnJHREdMbXcvcEZYCkZQcFZDbTF6Z1lTYjF2NlFu
27
+ ZjNjZ1hhMmYyd1lHbTE3K3pBVnlJRHB3cnlGcnU5eUYvakp4RTM4ei9EUnNk
28
+ OVIKLzg4Q0F3RUFBYU01TURjd0NRWURWUjBUQkFJd0FEQWRCZ05WSFE0RUZn
29
+ UVVzaU5uWEh0S2VNWVljcjR5SlZtUQpXT05MK0l3d0N3WURWUjBQQkFRREFn
30
+ U3dNQTBHQ1NxR1NJYjNEUUVCQlFVQUE0SUJBUUFseU43a0tvL05RQ1EwCkFP
31
+ elpMWjNXQWVQdlN0a0NGSUo1M3RzdjVLeW80cE1BbGx2K0JnUHp6QnQ3cWk2
32
+ MDVtRlNMNnpCZDl1TG91K1cKQ28zczQ4cDFkeTdDampBZlZRZG1WTkhGM013
33
+ WHRmQzJPRXl2U1FQaTR4S1I4aWJhOHdhM3hwOUxWbzFQdUxwdwovNkRzckNo
34
+ V3c3NEhmc0pONnFKT0s2ODRoSmVUOGxCWUFVZmlDM3dEMG93b1BTZytYdHlB
35
+ QWRkaXNSK0tWNVkxCk5tVkh1THRRY05UWnkrZ1JodDNhaEpSTXVDNlF5TG1r
36
+ VHNmKzZNYWVud0FNa0FnSGRzd0dzSnp0T25ObkJhM0YKeTBrQ1NXbUs2RCt4
37
+ L1NiZlM2cjdLZTA3TVJxemlKZEI5R3VFMSswY0lSdUZoOEVRK0xONkhYQ0tN
38
+ NXBvbi9HVQp5Y3dNWGZsMAotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
39
+ date: 2013-02-18 00:00:00.000000000 Z
40
+ dependencies:
41
+ - !ruby/object:Gem::Dependency
42
+ name: json
43
+ requirement: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ! '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ description: Audit all Gemfiles of a user/organization on github for unpatched versions
58
+ email: michael@grosser.it
59
+ executables:
60
+ - bundle-organization-audit
61
+ extensions: []
62
+ extra_rdoc_files: []
63
+ files:
64
+ - .gitignore
65
+ - .travis.yml
66
+ - Gemfile
67
+ - Gemfile.lock
68
+ - Rakefile
69
+ - Readme.md
70
+ - bin/bundle-organization-audit
71
+ - bundler-organization_audit.gemspec
72
+ - gem-public_cert.pem
73
+ - lib/bundler/organization_audit.rb
74
+ - lib/bundler/organization_audit/repo.rb
75
+ - lib/bundler/organization_audit/version.rb
76
+ - spec/bundler/organization_audit/repo_spec.rb
77
+ - spec/bundler/organization_audit_spec.rb
78
+ - spec/private.example.yml
79
+ - spec/spec_helper.rb
80
+ homepage: http://github.com/grosser/bundler-organization_audit
81
+ licenses:
82
+ - MIT
83
+ post_install_message:
84
+ rdoc_options: []
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ! '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ segments:
94
+ - 0
95
+ hash: 75415256473976345
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ segments:
103
+ - 0
104
+ hash: 75415256473976345
105
+ requirements: []
106
+ rubyforge_project:
107
+ rubygems_version: 1.8.24
108
+ signing_key:
109
+ specification_version: 3
110
+ summary: Audit all Gemfiles of a user/organization on github for unpatched versions
111
+ test_files: []
Binary file