summaryrefslogtreecommitdiff
path: root/lib/bundler/remote_specification.rb
diff options
context:
space:
mode:
authorMercedes Bernard <mercedesrbernard@gmail.com>2023-02-10 13:34:30 -0600
committerHiroshi SHIBATA <hsbt@ruby-lang.org>2023-10-23 13:59:01 +0900
commit69d7e9a12eb6e3dbfa1b1021b73c2afcbf7d4a46 (patch)
tree10e56a9112f606e866624095ec8acacce0500288 /lib/bundler/remote_specification.rb
parentad08674d8dc17c4ca031ce20760c4a4779c83e27 (diff)
[rubygems/rubygems] Use the server checksum, then calculate from gem on disk if possible
1. Use the checksum provided by the server if provided: provides security knowing if the gem you downloaded matches the gem on the server 2. Calculate the checksum from the gem on disk: provides security knowing if the gem has changed between installs 3. In some cases, neither is possible in which case we don't put anything in the checksum and we maintain functionality as it is today Add the checksums to specs in the index if we already have them Prior to checksums, we didn't lose any information when overwriting specs in the index with stubs. But now when we overwrite EndpointSpecifications or RemoteSpecifications with more generic specs, we could lose checksum info. This manually sets checksum info so we keep it in the index. https://github.com/rubygems/rubygems/commit/de00a4f153
Diffstat (limited to 'lib/bundler/remote_specification.rb')
-rw-r--r--lib/bundler/remote_specification.rb44
1 files changed, 44 insertions, 0 deletions
diff --git a/lib/bundler/remote_specification.rb b/lib/bundler/remote_specification.rb
index f626a3218e..e8054dbbd5 100644
--- a/lib/bundler/remote_specification.rb
+++ b/lib/bundler/remote_specification.rb
@@ -93,12 +93,56 @@ module Bundler
" #{source.revision[0..6]}"
end
+ # we don't get the checksum from a server like we could with EndpointSpecs
+ # calculating the checksum from the file on disk still provides some measure of security
+ # if it changes from install to install, that is cause for concern
+ def to_checksum
+ @checksum ||= begin
+ gem_path = fetch_gem
+ require "rubygems/package"
+ package = Gem::Package.new(gem_path)
+ digest = Bundler::Checksum.digest_from_file_source(package.gem)
+ digest.hexdigest!
+ end
+
+ digest = "sha256-#{@checksum}" if @checksum
+ Bundler::Checksum.new(name, version, platform, [digest])
+ end
+
private
def to_ary
nil
end
+ def fetch_gem
+ fetch_platform
+
+ cache_path = download_cache_path || default_cache_path_for_rubygems_dir
+ gem_path = "#{cache_path}/#{file_name}"
+ return gem_path if File.exist?(gem_path)
+
+ SharedHelpers.filesystem_access(cache_path) do |p|
+ FileUtils.mkdir_p(p)
+ end
+
+ Bundler.rubygems.download_gem(self, remote.uri, cache_path)
+
+ gem_path
+ end
+
+ def download_cache_path
+ return unless Bundler.feature_flag.global_gem_cache?
+ return unless remote
+ return unless remote.cache_slug
+
+ Bundler.user_cache.join("gems", remote.cache_slug)
+ end
+
+ def default_cache_path_for_rubygems_dir
+ "#{Bundler.bundle_path}/cache"
+ end
+
def _remote_specification
@_remote_specification ||= @spec_fetcher.fetch_spec([@name, @version, @original_platform])
@_remote_specification || raise(GemspecError, "Gemspec data for #{full_name} was" \