Skip to content

Commit 290437a

Browse files
Enforce checksums strictly for registry gems
1 parent 233a558 commit 290437a

File tree

4 files changed

+101
-7
lines changed

4 files changed

+101
-7
lines changed

bundler/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

bundler/lib/bundler/definition.rb

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,7 @@ def something_changed?
559559
@missing_lockfile_dep ||
560560
@unlocking_bundler ||
561561
@locked_spec_with_missing_checksums ||
562+
@locked_spec_with_empty_checksums ||
562563
@locked_spec_with_missing_deps ||
563564
@locked_spec_with_invalid_deps
564565
end
@@ -839,6 +840,7 @@ def lockfile_changed_reason
839840
[@missing_lockfile_dep, "your lockfile is missing \"#{@missing_lockfile_dep}\""],
840841
[@unlocking_bundler, "an update to the version of Bundler itself was requested"],
841842
[@locked_spec_with_missing_checksums, "your lockfile is missing a CHECKSUMS entry for \"#{@locked_spec_with_missing_checksums}\""],
843+
[@locked_spec_with_empty_checksums, "your lockfile has an empty CHECKSUMS entry for \"#{@locked_spec_with_empty_checksums}\""],
842844
[@locked_spec_with_missing_deps, "your lockfile includes \"#{@locked_spec_with_missing_deps}\" but not some of its dependencies"],
843845
[@locked_spec_with_invalid_deps, "your lockfile does not satisfy dependencies of \"#{@locked_spec_with_invalid_deps}\""],
844846
].select(&:first).map(&:last).join(", ")
@@ -898,13 +900,23 @@ def check_lockfile
898900
@locked_spec_with_invalid_deps = nil
899901
@locked_spec_with_missing_deps = nil
900902
@locked_spec_with_missing_checksums = nil
903+
@locked_spec_with_empty_checksums = nil
901904

902905
missing_deps = []
903906
missing_checksums = []
907+
empty_checksums = []
904908
invalid = []
905909

906910
@locked_specs.each do |s|
907-
missing_checksums << s if @locked_checksums && s.source.checksum_store.missing?(s)
911+
if @locked_checksums
912+
checksum_store = s.source.checksum_store
913+
914+
if checksum_store.missing?(s)
915+
missing_checksums << s
916+
elsif checksum_store.empty?(s)
917+
empty_checksums << s
918+
end
919+
end
908920

909921
validation = @locked_specs.validate_deps(s)
910922

@@ -913,6 +925,7 @@ def check_lockfile
913925
end
914926

915927
@locked_spec_with_missing_checksums = missing_checksums.first.name if missing_checksums.any?
928+
@locked_spec_with_empty_checksums = empty_checksums.first.name if empty_checksums.any?
916929

917930
if missing_deps.any?
918931
@locked_specs.delete(missing_deps)

bundler/spec/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

bundler/spec/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)