Skip to content

Commit 8576da4

Browse files
deivid-rodriguezhsbt
authored andcommitted
[rubygems/rubygems] Enforce checksums strictly for registry gems
ruby/rubygems@05199ae0c1
1 parent 50c1fae commit 8576da4

File tree

4 files changed

+101
-7
lines changed

4 files changed

+101
-7
lines changed

lib/bundler/checksum.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,12 @@ def missing?(spec)
205205
@store[spec.lock_name].nil?
206206
end
207207

208+
def empty?(spec)
209+
return false unless spec.source.is_a?(Bundler::Source::Rubygems)
210+
211+
@store[spec.lock_name].empty?
212+
end
213+
208214
def register(spec, checksum)
209215
register_checksum(spec.lock_name, checksum)
210216
end

lib/bundler/definition.rb

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,7 @@ def something_changed?
557557
@missing_lockfile_dep ||
558558
@unlocking_bundler ||
559559
@locked_spec_with_missing_checksums ||
560+
@locked_spec_with_empty_checksums ||
560561
@locked_spec_with_missing_deps ||
561562
@locked_spec_with_invalid_deps
562563
end
@@ -836,6 +837,7 @@ def lockfile_changed_reason
836837
[@missing_lockfile_dep, "your lockfile is missing \"#{@missing_lockfile_dep}\""],
837838
[@unlocking_bundler, "an update to the version of Bundler itself was requested"],
838839
[@locked_spec_with_missing_checksums, "your lockfile is missing a CHECKSUMS entry for \"#{@locked_spec_with_missing_checksums}\""],
840+
[@locked_spec_with_empty_checksums, "your lockfile has an empty CHECKSUMS entry for \"#{@locked_spec_with_empty_checksums}\""],
839841
[@locked_spec_with_missing_deps, "your lockfile includes \"#{@locked_spec_with_missing_deps}\" but not some of its dependencies"],
840842
[@locked_spec_with_invalid_deps, "your lockfile does not satisfy dependencies of \"#{@locked_spec_with_invalid_deps}\""],
841843
].select(&:first).map(&:last).join(", ")
@@ -895,13 +897,23 @@ def check_lockfile
895897
@locked_spec_with_invalid_deps = nil
896898
@locked_spec_with_missing_deps = nil
897899
@locked_spec_with_missing_checksums = nil
900+
@locked_spec_with_empty_checksums = nil
898901

899902
missing_deps = []
900903
missing_checksums = []
904+
empty_checksums = []
901905
invalid = []
902906

903907
@locked_specs.each do |s|
904-
missing_checksums << s if @locked_checksums && s.source.checksum_store.missing?(s)
908+
if @locked_checksums
909+
checksum_store = s.source.checksum_store
910+
911+
if checksum_store.missing?(s)
912+
missing_checksums << s
913+
elsif checksum_store.empty?(s)
914+
empty_checksums << s
915+
end
916+
end
905917

906918
validation = @locked_specs.validate_deps(s)
907919

@@ -910,6 +922,7 @@ def check_lockfile
910922
end
911923

912924
@locked_spec_with_missing_checksums = missing_checksums.first.name if missing_checksums.any?
925+
@locked_spec_with_empty_checksums = empty_checksums.first.name if empty_checksums.any?
913926

914927
if missing_deps.any?
915928
@locked_specs.delete(missing_deps)

spec/bundler/install/gemfile/git_spec.rb

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,23 @@
22

33
RSpec.describe "bundle install with git sources" do
44
describe "when floating on main" do
5-
let(:install_base_gemfile) do
6-
build_git "foo" do |s|
7-
s.executables = "foobar"
8-
end
9-
10-
install_gemfile <<-G
5+
let(:base_gemfile) do
6+
<<-G
117
source "https://gem.repo1"
128
git "#{lib_path("foo-1.0")}" do
139
gem 'foo'
1410
end
1511
G
1612
end
1713

14+
let(:install_base_gemfile) do
15+
build_git "foo" do |s|
16+
s.executables = "foobar"
17+
end
18+
19+
install_gemfile base_gemfile
20+
end
21+
1822
it "fetches gems" do
1923
install_base_gemfile
2024
expect(the_bundle).to include_gems("foo 1.0")
@@ -27,6 +31,43 @@
2731
expect(out).to eq("WIN")
2832
end
2933

34+
it "does not (yet?) enforce CHECKSUMS" do
35+
build_git "foo"
36+
revision = revision_for(lib_path("foo-1.0"))
37+
38+
bundle "config set lockfile_checksums true"
39+
gemfile base_gemfile
40+
41+
lockfile <<~L
42+
GIT
43+
remote: #{lib_path("foo-1.0")}
44+
revision: #{revision}
45+
specs:
46+
foo (1.0)
47+
48+
GEM
49+
remote: https://gem.repo1/
50+
specs:
51+
52+
PLATFORMS
53+
#{lockfile_platforms}
54+
55+
DEPENDENCIES
56+
foo!
57+
58+
CHECKSUMS
59+
foo (1.0)
60+
61+
BUNDLED WITH
62+
#{Bundler::VERSION}
63+
L
64+
65+
bundle "config set frozen true"
66+
67+
bundle "install"
68+
expect(the_bundle).to include_gems("foo 1.0")
69+
end
70+
3071
it "caches the git repo" do
3172
install_base_gemfile
3273
expect(Dir["#{default_bundle_path}/cache/bundler/git/foo-1.0-*"]).to have_attributes size: 1

spec/bundler/lock/lockfile_spec.rb

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1646,6 +1646,40 @@
16461646
expect(the_bundle).not_to include_gems "myrack_middleware 1.0"
16471647
end
16481648

1649+
it "raises a clear error when frozen mode is set and lockfile has empty checksums in CHECKSUMS section, and does not install any gems" do
1650+
lockfile <<-L
1651+
GEM
1652+
remote: https://gem.repo2/
1653+
specs:
1654+
myrack (0.9.1)
1655+
1656+
PLATFORMS
1657+
#{lockfile_platforms}
1658+
1659+
DEPENDENCIES
1660+
myrack
1661+
1662+
CHECKSUMS
1663+
myrack (0.9.1)
1664+
1665+
BUNDLED WITH
1666+
#{Bundler::VERSION}
1667+
L
1668+
1669+
install_gemfile <<-G, env: { "BUNDLE_FROZEN" => "true" }, raise_on_error: false
1670+
source "https://gem.repo2"
1671+
gem "myrack"
1672+
G
1673+
1674+
expect(err).to eq <<~L.strip
1675+
Your lockfile has an empty CHECKSUMS entry for \"myrack\", but can't be updated because frozen mode is set
1676+
1677+
Run `bundle install` elsewhere and add the updated Gemfile.lock to version control.
1678+
L
1679+
1680+
expect(the_bundle).not_to include_gems "myrack 0.9.1"
1681+
end
1682+
16491683
it "automatically fixes the lockfile when it's missing deps, they conflict with other locked deps, but conflicts are fixable" do
16501684
build_repo4 do
16511685
build_gem "other_dep", "0.9"

0 commit comments

Comments
 (0)