Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gems/bundler-checksum/lib')
-rw-r--r--vendor/gems/bundler-checksum/lib/bundler-checksum.rb1
-rw-r--r--vendor/gems/bundler-checksum/lib/bundler/checksum.rb109
-rw-r--r--vendor/gems/bundler-checksum/lib/bundler/checksum/command.rb27
-rw-r--r--vendor/gems/bundler-checksum/lib/bundler/checksum/command/helper.rb28
-rw-r--r--vendor/gems/bundler-checksum/lib/bundler/checksum/command/init.rb66
-rw-r--r--vendor/gems/bundler-checksum/lib/bundler/checksum/command/verify.rb52
-rw-r--r--vendor/gems/bundler-checksum/lib/bundler/checksum/version.rb8
7 files changed, 291 insertions, 0 deletions
diff --git a/vendor/gems/bundler-checksum/lib/bundler-checksum.rb b/vendor/gems/bundler-checksum/lib/bundler-checksum.rb
new file mode 100644
index 00000000000..600cd4f7107
--- /dev/null
+++ b/vendor/gems/bundler-checksum/lib/bundler-checksum.rb
@@ -0,0 +1 @@
+require 'bundler/checksum'
diff --git a/vendor/gems/bundler-checksum/lib/bundler/checksum.rb b/vendor/gems/bundler-checksum/lib/bundler/checksum.rb
new file mode 100644
index 00000000000..c8d78eba111
--- /dev/null
+++ b/vendor/gems/bundler-checksum/lib/bundler/checksum.rb
@@ -0,0 +1,109 @@
+# frozen_string_literal: true
+
+require 'bundler'
+require 'bundler/checksum/version'
+require 'json'
+
+module Bundler
+ module Patches
+ # This module monkey-patches Bundler to check Gemfile.checksum
+ # when installing gems that are from RubyGems
+ module RubyGemsInstallerPatch
+ def pre_install_checks
+ super && validate_local_package_checksum
+ end
+
+ private
+
+ def validate_local_package_checksum
+ cached_checksum = fetch_checksum_from_file(spec)
+
+ if cached_checksum.nil?
+ raise SecurityError, "Cached checksum for #{spec.full_name} not found. Please (re-)generate Gemfile.checksum"
+ end
+
+ validate_file_checksum(cached_checksum)
+ end
+
+ def fetch_checksum_from_file(spec)
+ ::Bundler::Checksum.checksum_for(spec.name, spec.version.to_s, spec.platform.to_s)
+ end
+
+ # Modified from
+ # https://github.com/rubygems/rubygems/blob/243173279e79a38f03e318eea8825d1c8824e119/bundler/lib/bundler/rubygems_gem_installer.rb#L116
+ def validate_file_checksum(checksum)
+ return true if Bundler.settings[:disable_checksum_validation]
+
+ source = @package.instance_variable_get(:@gem)
+
+ # Contary to upstream, we raise instead of silently returning
+ raise "#{@package.inspect} does not have :@gem" unless source
+ raise "#{source.inspect} does not respond to :with_read_io" unless source.respond_to?(:with_read_io)
+
+ digest = source.with_read_io do |io|
+ digest = SharedHelpers.digest(:SHA256).new
+ digest << io.read(16_384) until io.eof?
+ io.rewind
+ send(checksum_type(checksum), digest)
+ end
+ unless digest == checksum
+ raise SecurityError, <<-MESSAGE
+ Bundler cannot continue installing #{spec.name} (#{spec.version}).
+ The checksum for the downloaded `#{spec.full_name}.gem` does not match \
+ the checksum from the checksum file. This means the contents of the downloaded \
+ gem is different from what was recorded in the checksum file, and could be potential security issue.
+ gem is different from what was uploaded to the server, and could be a potential security issue.
+
+ To resolve this issue:
+ 1. delete the downloaded gem located at: `#{spec.gem_dir}/#{spec.full_name}.gem`
+ 2. run `bundle install`
+
+ If you wish to continue installing the downloaded gem, and are certain it does not pose a \
+ security issue despite the mismatching checksum, do the following:
+ 1. run `bundle config set --local disable_checksum_validation true` to turn off checksum verification
+ 2. run `bundle install`
+
+ (More info: The expected SHA256 checksum was #{checksum.inspect}, but the \
+ checksum for the downloaded gem was #{digest.inspect}.)
+ MESSAGE
+ end
+ true
+ end
+ end
+ end
+end
+
+module Bundler
+ module Checksum
+ class << self
+ def checksum_file
+ @checksum_file ||= File.join(File.dirname(Bundler.default_gemfile), 'Gemfile.checksum')
+ end
+
+ def checksums_from_file
+ @checksums_from_file ||= JSON.parse(File.open(checksum_file).read, symbolize_names: true)
+ rescue JSON::ParserError => e
+ raise "Invalid checksum file: #{e.message}"
+ end
+
+ def checksum_for(gem_name, gem_version, gem_platform)
+ item = checksums_from_file.detect do |item|
+ item[:name] == gem_name &&
+ item[:platform] == gem_platform &&
+ item[:version] == gem_version
+ end
+
+ item&.fetch(:checksum)
+ end
+
+ def patch!
+ return if defined?(@patched) && @patched
+ @patched = true
+
+ Bundler.ui.info "Patching bundler with bundler-checksum..."
+ require 'bundler/rubygems_gem_installer'
+ ::Bundler::RubyGemsGemInstaller.prepend(Bundler::Patches::RubyGemsInstallerPatch)
+ end
+ end
+ end
+end
diff --git a/vendor/gems/bundler-checksum/lib/bundler/checksum/command.rb b/vendor/gems/bundler-checksum/lib/bundler/checksum/command.rb
new file mode 100644
index 00000000000..438f41f6e69
--- /dev/null
+++ b/vendor/gems/bundler-checksum/lib/bundler/checksum/command.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Bundler::Checksum
+ module Command
+ autoload :Init, File.expand_path("command/init", __dir__)
+ autoload :Verify, File.expand_path("command/verify", __dir__)
+ autoload :Helper, File.expand_path("command/helper", __dir__)
+
+ def self.execute(args)
+ if args.empty?
+ $stderr.puts 'A command must be given [init,update,verify]'
+ end
+
+ if args.first == 'init'
+ Init.execute
+ elsif args.first == 'update'
+ $stderr.puts 'Not implemented, please use init'
+ elsif args.first == 'verify'
+ verified = Verify.execute
+
+ unless verified
+ exit 1
+ end
+ end
+ end
+ end
+end
diff --git a/vendor/gems/bundler-checksum/lib/bundler/checksum/command/helper.rb b/vendor/gems/bundler-checksum/lib/bundler/checksum/command/helper.rb
new file mode 100644
index 00000000000..fa06bfe3da4
--- /dev/null
+++ b/vendor/gems/bundler-checksum/lib/bundler/checksum/command/helper.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require 'json'
+require 'net/http'
+
+module Bundler::Checksum::Command
+ module Helper
+ extend self
+
+ def remote_checksums_for_gem(gem_name, gem_version)
+ response = Net::HTTP.get_response(URI(
+ "https://rubygems.org/api/v1/versions/#{gem_name}.json"
+ ))
+
+ return [] unless response.code == '200'
+
+ gem_candidates = JSON.parse(response.body, symbolize_names: true)
+ gem_candidates.select! { |g| g[:number] == gem_version.to_s }
+
+ gem_candidates.map {
+ |g| {:name => gem_name, :version => gem_version, :platform => g[:platform], :checksum => g[:sha]}
+ }
+
+ rescue JSON::ParserError
+ []
+ end
+ end
+end
diff --git a/vendor/gems/bundler-checksum/lib/bundler/checksum/command/init.rb b/vendor/gems/bundler-checksum/lib/bundler/checksum/command/init.rb
new file mode 100644
index 00000000000..fed0e11080f
--- /dev/null
+++ b/vendor/gems/bundler-checksum/lib/bundler/checksum/command/init.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+require 'openssl'
+
+module Bundler::Checksum::Command
+ module Init
+ extend self
+
+ def execute
+ $stderr.puts "Initializing checksum file #{checksum_file}"
+
+ checksums = []
+
+ compact_index_cache = Bundler::Fetcher::CompactIndex
+ .new(nil, Bundler::Source::Rubygems::Remote.new(Bundler::URI("https://rubygems.org")), nil)
+ .send(:compact_index_client)
+ .instance_variable_get(:@cache)
+
+ seen = []
+ Bundler.definition.resolve.sort_by(&:name).each do |spec|
+ next unless spec.source.is_a?(Bundler::Source::Rubygems)
+
+ next if seen.include?(spec.name)
+ seen << spec.name
+
+ $stderr.puts "Adding #{spec.name}==#{spec.version}"
+
+ compact_index_dependencies = compact_index_cache.dependencies(spec.name).select { |item| item.first == spec.version.to_s }
+
+ if !compact_index_dependencies.empty?
+ compact_index_checksums = compact_index_dependencies.map do |version, platform, dependencies, requirements|
+ {
+ name: spec.name,
+ version: spec.version.to_s,
+ platform: Gem::Platform.new(platform).to_s,
+ checksum: requirements.detect { |requirement| requirement.first == 'checksum' }.flatten[1]
+ }
+ end
+
+ checksums += compact_index_checksums.sort_by { |hash| hash.values }
+ else
+ remote_checksum = Helper.remote_checksums_for_gem(spec.name, spec.version)
+
+ if remote_checksum.empty?
+ raise "#{spec.name} #{spec.version} not found on Rubygems!"
+ end
+
+ checksums += remote_checksum.sort_by { |hash| hash.values }
+ end
+ end
+
+ File.write(checksum_file, JSON.generate(checksums, array_nl: "\n") + "\n")
+ end
+
+ private
+
+ def checksum_file
+ ::Bundler::Checksum.checksum_file
+ end
+
+ def lockfile
+ lockfile_path = Bundler.default_lockfile
+ lockfile = Bundler::LockfileParser.new(Bundler.read_file(lockfile_path))
+ end
+ end
+end
diff --git a/vendor/gems/bundler-checksum/lib/bundler/checksum/command/verify.rb b/vendor/gems/bundler-checksum/lib/bundler/checksum/command/verify.rb
new file mode 100644
index 00000000000..ba2eea6ea0c
--- /dev/null
+++ b/vendor/gems/bundler-checksum/lib/bundler/checksum/command/verify.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+module Bundler::Checksum::Command
+ module Verify
+ extend self
+
+ def execute
+ $stderr.puts 'Verifying bundle checksums'
+
+ verified = true
+
+ local_checksums.each do |gem|
+ name = gem.fetch(:name)
+ version = gem.fetch(:version)
+ platform = gem.fetch(:platform)
+ checksum = gem.fetch(:checksum)
+
+ $stderr.puts "Verifying #{name}==#{version} #{platform}"
+ unless validate_gem_checksum(name, version, platform, checksum)
+ verified = false
+ end
+ end
+
+ verified
+ end
+
+ private
+
+ def local_checksums
+ ::Bundler::Checksum.checksums_from_file
+ end
+
+ def validate_gem_checksum(gem_name, gem_version, gem_platform, local_checksum)
+ remote_checksums = Helper.remote_checksums_for_gem(gem_name, gem_version)
+ if remote_checksums.empty?
+ $stderr.puts "#{gem_name} #{gem_version} not found on Rubygems, skipping"
+ return false
+ end
+
+ remote_platform_checksum = remote_checksums.find { |g| g[:name] == gem_name && g[:platform] == gem_platform.to_s }
+
+ if local_checksum == remote_platform_checksum[:checksum]
+ true
+ else
+ $stderr.puts "Gem #{gem_name} #{gem_version} #{gem_platform} failed checksum verification"
+ $stderr.puts "LOCAL: #{local_checksum}"
+ $stderr.puts "REMOTE: #{remote_platform_checksum[:checksum]}"
+ return false
+ end
+ end
+ end
+end
diff --git a/vendor/gems/bundler-checksum/lib/bundler/checksum/version.rb b/vendor/gems/bundler-checksum/lib/bundler/checksum/version.rb
new file mode 100644
index 00000000000..41e958b2db9
--- /dev/null
+++ b/vendor/gems/bundler-checksum/lib/bundler/checksum/version.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+module Bundler
+ module Checksum
+ # bundler-checksum version
+ VERSION = '0.1.0'
+ end
+end