aboutsummaryrefslogtreecommitdiffstats
path: root/spec/bundler/install/gemfile/sources_spec.rb
diff options
context:
space:
mode:
authorMartin Emde <martin.emde@gmail.com>2023-09-01 15:15:49 -0700
committerHiroshi SHIBATA <hsbt@ruby-lang.org>2023-10-23 13:59:01 +0900
commitc667de72ff9de195e1cab4b1937973e841ff89ae (patch)
tree6dc6a88dbf8c44109593352055c8e798d562a83f /spec/bundler/install/gemfile/sources_spec.rb
parent6362bfdc337c1929a381734ded417b796f9767bf (diff)
downloadruby-c667de72ff9de195e1cab4b1937973e841ff89ae.tar.gz
[rubygems/rubygems] Improve errors and register checksums reliably
Improve error reporting for checksums, raises a new error class. Solve for multi-source checksum errors. Add CHECKSUMS to tool/bundler/(dev|standard|rubocop)26_gems.rb https://github.com/rubygems/rubygems/commit/26ceee0e76 Co-authored-by: Samuel Giddins <segiddins@segiddins.me>
Diffstat (limited to 'spec/bundler/install/gemfile/sources_spec.rb')
-rw-r--r--spec/bundler/install/gemfile/sources_spec.rb187
1 files changed, 167 insertions, 20 deletions
diff --git a/spec/bundler/install/gemfile/sources_spec.rb b/spec/bundler/install/gemfile/sources_spec.rb
index 72658aebd9..16b9d82104 100644
--- a/spec/bundler/install/gemfile/sources_spec.rb
+++ b/spec/bundler/install/gemfile/sources_spec.rb
@@ -27,27 +27,55 @@ RSpec.describe "bundle install with gems on multiple sources" do
G
end
- it "warns about ambiguous gems, but installs anyway, prioritizing sources last to first", :bundler => "< 3" do
- bundle :install, :artifice => "compact_index"
+ it "refuses to install mismatched checksum because one gem has been tampered with", :bundler => "< 3" do
+ bundle :install, :artifice => "compact_index", :raise_on_error => false
- expect(err).to include("Warning: the gem 'rack' was found in multiple sources.")
- expect(err).to include("Installed from: https://gem.repo1")
- expect(the_bundle).to include_gems("rack-obama 1.0.0", "rack 1.0.0", :source => "remote1")
+ expect(exitstatus).to eq(37)
+ expect(err).to eq <<~E.strip
+ [DEPRECATED] Your Gemfile contains multiple global sources. Using `source` more than once without a block is a security risk, and may result in installing unexpected gems. To resolve this warning, use a block to indicate which gems should come from the secondary source.
+ Bundler found mismatched checksums. This is a potential security risk.
+ #{checksum_for_repo_gem(gem_repo1, "rack", "1.0.0")}
+ from the API at https://gem.repo1/
+ #{checksum_for_repo_gem(gem_repo3, "rack", "1.0.0")}
+ from the API at https://gem.repo3/
+
+ Mismatched checksums each have an authoritative source:
+ 1. the API at https://gem.repo1/
+ 2. the API at https://gem.repo3/
+ You may need to alter your Gemfile sources to resolve this issue.
+
+ To ignore checksum security warnings, disable checksum validation with
+ `bundle config set --local disable_checksum_validation true`
+ E
end
- it "does not use the full index unnecessarily", :bundler => "< 3" do
- bundle :install, :artifice => "compact_index", :verbose => true
+ context "when checksum validation is disabled" do
+ before do
+ bundle "config set --local disable_checksum_validation true"
+ end
- expect(out).to include("https://gem.repo1/versions")
- expect(out).to include("https://gem.repo3/versions")
- expect(out).not_to include("https://gem.repo1/quick/Marshal.4.8/")
- expect(out).not_to include("https://gem.repo3/quick/Marshal.4.8/")
- end
+ it "warns about ambiguous gems, but installs anyway, prioritizing sources last to first", :bundler => "< 3" do
+ bundle :install, :artifice => "compact_index"
- it "fails", :bundler => "3" do
- bundle :install, :artifice => "compact_index", :raise_on_error => false
- expect(err).to include("Each source after the first must include a block")
- expect(exitstatus).to eq(4)
+ expect(err).to include("Warning: the gem 'rack' was found in multiple sources.")
+ expect(err).to include("Installed from: https://gem.repo1")
+ expect(the_bundle).to include_gems("rack-obama 1.0.0", "rack 1.0.0", :source => "remote1")
+ end
+
+ it "does not use the full index unnecessarily", :bundler => "< 3" do
+ bundle :install, :artifice => "compact_index", :verbose => true
+
+ expect(out).to include("https://gem.repo1/versions")
+ expect(out).to include("https://gem.repo3/versions")
+ expect(out).not_to include("https://gem.repo1/quick/Marshal.4.8/")
+ expect(out).not_to include("https://gem.repo3/quick/Marshal.4.8/")
+ end
+
+ it "fails", :bundler => "3" do
+ bundle :install, :artifice => "compact_index", :raise_on_error => false
+ expect(err).to include("Each source after the first must include a block")
+ expect(exitstatus).to eq(4)
+ end
end
end
@@ -101,7 +129,8 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
it "works in standalone mode", :bundler => "< 3" do
- bundle "install --standalone", :artifice => "compact_index"
+ gem_checksum = checksum_for_repo_gem(gem_repo4, "foo", "1.0").split("-").last
+ bundle "install --standalone", :artifice => "compact_index", :env => { "BUNDLER_SPEC_FOO_CHECKSUM" => gem_checksum }
end
end
@@ -279,8 +308,55 @@ RSpec.describe "bundle install with gems on multiple sources" do
G
end
- it "installs from the other source and warns about ambiguous gems", :bundler => "< 3" do
- bundle :install, :artifice => "compact_index"
+ it "fails when the two sources don't have the same checksum", :bundler => "< 3" do
+ bundle :install, :artifice => "compact_index", :raise_on_error => false
+
+ expect(err).to eq(<<~E.strip)
+ [DEPRECATED] Your Gemfile contains multiple global sources. Using `source` more than once without a block is a security risk, and may result in installing unexpected gems. To resolve this warning, use a block to indicate which gems should come from the secondary source.
+ Bundler found mismatched checksums. This is a potential security risk.
+ #{checksum_for_repo_gem(gem_repo2, "rack", "1.0.0")}
+ from the API at https://gem.repo2/
+ #{checksum_for_repo_gem(gem_repo1, "rack", "1.0.0")}
+ from the API at https://gem.repo1/
+
+ Mismatched checksums each have an authoritative source:
+ 1. the API at https://gem.repo2/
+ 2. the API at https://gem.repo1/
+ You may need to alter your Gemfile sources to resolve this issue.
+
+ To ignore checksum security warnings, disable checksum validation with
+ `bundle config set --local disable_checksum_validation true`
+ E
+ expect(exitstatus).to eq(37)
+ end
+
+ it "fails when the two sources agree, but the local gem calculates a different checksum", :bundler => "< 3" do
+ rack_checksum = "c0ffee11" * 8
+ bundle :install, :artifice => "compact_index", :env => { "BUNDLER_SPEC_RACK_CHECKSUM" => rack_checksum }, :raise_on_error => false
+
+ expect(err).to eq(<<~E.strip)
+ [DEPRECATED] Your Gemfile contains multiple global sources. Using `source` more than once without a block is a security risk, and may result in installing unexpected gems. To resolve this warning, use a block to indicate which gems should come from the secondary source.
+ Bundler found mismatched checksums. This is a potential security risk.
+ rack (1.0.0) sha256-#{rack_checksum}
+ from the API at https://gem.repo2/
+ and the API at https://gem.repo1/
+ #{checksum_for_repo_gem(gem_repo2, "rack", "1.0.0")}
+ from the gem at #{default_bundle_path("cache", "rack-1.0.0.gem")}
+
+ If you trust the API at https://gem.repo2/, to resolve this issue you can:
+ 1. remove the gem at #{default_bundle_path("cache", "rack-1.0.0.gem")}
+ 2. run `bundle install`
+
+ To ignore checksum security warnings, disable checksum validation with
+ `bundle config set --local disable_checksum_validation true`
+ E
+ expect(exitstatus).to eq(37)
+ end
+
+ it "installs from the other source and warns about ambiguous gems when the sources have the same checksum", :bundler => "< 3" do
+ gem_checksum = checksum_for_repo_gem(gem_repo2, "rack", "1.0.0").split("-").last
+ bundle :install, :artifice => "compact_index", :env => { "BUNDLER_SPEC_RACK_CHECKSUM" => gem_checksum, "DEBUG" => "1" }
+
expect(err).to include("Warning: the gem 'rack' was found in multiple sources.")
expect(err).to include("Installed from: https://gem.repo2")
@@ -320,6 +396,49 @@ RSpec.describe "bundle install with gems on multiple sources" do
expect(lockfile).to eq(previous_lockfile)
end
+ it "installs from the other source and warns about ambiguous gems when checksum validation is disabled", :bundler => "< 3" do
+ bundle "config set --local disable_checksum_validation true"
+ bundle :install, :artifice => "compact_index"
+
+ expect(err).to include("Warning: the gem 'rack' was found in multiple sources.")
+ expect(err).to include("Installed from: https://gem.repo2")
+
+ expected_checksums = checksum_section do |c|
+ c.no_checksum "depends_on_rack", "1.0.1"
+ c.no_checksum "rack", "1.0.0"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo1/
+ remote: https://gem.repo2/
+ specs:
+ rack (1.0.0)
+
+ GEM
+ remote: https://gem.repo3/
+ specs:
+ depends_on_rack (1.0.1)
+ rack
+
+ PLATFORMS
+ #{local_platform}
+
+ DEPENDENCIES
+ depends_on_rack!
+
+ CHECKSUMS
+ #{expected_checksums}
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ previous_lockfile = lockfile
+ expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
+ expect(lockfile).to eq(previous_lockfile)
+ end
+
it "fails", :bundler => "3" do
bundle :install, :artifice => "compact_index", :raise_on_error => false
expect(err).to include("Each source after the first must include a block")
@@ -1167,8 +1286,9 @@ RSpec.describe "bundle install with gems on multiple sources" do
lockfile aggregate_gem_section_lockfile
end
- it "installs the existing lockfile but prints a warning", :bundler => "< 3" do
+ it "installs the existing lockfile but prints a warning when checksum validation is disabled", :bundler => "< 3" do
bundle "config set --local deployment true"
+ bundle "config set --local disable_checksum_validation true"
bundle "install", :artifice => "compact_index"
@@ -1177,6 +1297,33 @@ RSpec.describe "bundle install with gems on multiple sources" do
expect(the_bundle).to include_gems("rack 0.9.1", :source => "remote3")
end
+ it "prints a checksum warning when the checksums from both sources do not match", :bundler => "< 3" do
+ bundle "config set --local deployment true"
+
+ bundle "install", :artifice => "compact_index", :raise_on_error => false
+
+ api_checksum1 = checksum_for_repo_gem(gem_repo1, "rack", "0.9.1").split("sha256-").last
+ api_checksum3 = checksum_for_repo_gem(gem_repo3, "rack", "0.9.1").split("sha256-").last
+
+ expect(exitstatus).to eq(37)
+ expect(err).to eq(<<~E.strip)
+ [DEPRECATED] Your lockfile contains a single rubygems source section with multiple remotes, which is insecure. Make sure you run `bundle install` in non frozen mode and commit the result to make your lockfile secure.
+ Bundler found mismatched checksums. This is a potential security risk.
+ rack (0.9.1) sha256-#{api_checksum3}
+ from the API at https://gem.repo3/
+ rack (0.9.1) sha256-#{api_checksum1}
+ from the API at https://gem.repo1/
+
+ Mismatched checksums each have an authoritative source:
+ 1. the API at https://gem.repo3/
+ 2. the API at https://gem.repo1/
+ You may need to alter your Gemfile sources to resolve this issue.
+
+ To ignore checksum security warnings, disable checksum validation with
+ `bundle config set --local disable_checksum_validation true`
+ E
+ end
+
it "refuses to install the existing lockfile and prints an error", :bundler => "3" do
bundle "config set --local deployment true"