diff options
author | Martin Emde <martin.emde@gmail.com> | 2023-09-01 15:15:49 -0700 |
---|---|---|
committer | Hiroshi SHIBATA <hsbt@ruby-lang.org> | 2023-10-23 13:59:01 +0900 |
commit | c667de72ff9de195e1cab4b1937973e841ff89ae (patch) | |
tree | 6dc6a88dbf8c44109593352055c8e798d562a83f /spec/bundler/install/gemfile/sources_spec.rb | |
parent | 6362bfdc337c1929a381734ded417b796f9767bf (diff) | |
download | ruby-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.rb | 187 |
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" |