# Vulnerability Summary ## Vulnerability Overview - **Vulnerability ID**: CVE-2026-32148 - **Vulnerability Description**: Due to a type mismatch in the `mix.lock` file, checksum verification is silently skipped. Specifically, when comparing atom-based names with string-based lock data during pattern matching, checksum verification is not executed correctly. - **Fix Commit**: Commit d7528c8 ## Impact Scope - **Affected File**: `lib/hex/remote_converger.ex` - **Affected Functions**: `verify_deps/4` and `verify_deps/5` ## Remediation - **Fixed File**: `lib/hex/remote_converger.ex` - **Fix Details**: - In the `verify_deps/4` and `verify_deps/5` functions, atom-based names are converted to string-based names to ensure checksum verification is executed correctly. - Specific modifications are as follows: ```elixir # Before fix case Hex.Util.lock[lock[atom_to_string(app)]] do %{name: atom_name, version: version, repo: repo} = lock -> %{name: atom_name, version: version, repo: repo} = lock # After fix case Hex.Util.lock[lock[String.to_atom(app)]] do %{name: atom_name, version: version, repo: repo} = lock -> %{name: atom_name, version: version, repo: repo} = lock ``` ## POC Code - **Test File**: `test/hex/remote_converger_test.exs` - **Test Content**: - The test case `test "raises an checksum mismatch in mix.lock" do` is used to verify the checksum verification functionality after the fix. - Specific test code is as follows: ```elixir test "raises an checksum mismatch in mix.lock" do in_tmp(fn -> Mix.Project.push(ChecksumIntegrity.MixProject) # First, get dependencies normally to create a valid lock file :ok = Mix.Tasks.Deps.Get.run([]) # Read the lock file lock = Mix.Dep.Lock.read() {:hex, name, version, inner_checksum, managers, deps, repo, outer_checksum} = lock[:ex_doc] assert_checksum_mismatch(%{ ex_doc: {:hex, name, version, invalid_checksum(inner_checksum), managers, deps, repo, outer_checksum} }) assert_checksum_mismatch(%{ ex_doc: {:hex, name, version, inner_checksum, managers, deps, repo, invalid_checksum(outer_checksum)} }) end) end defp assert_checksum_mismatch(lock) do File.write!("mix.lock", inspect(lock, limit: :infinity, pretty: true)) Mix.Tasks.clear() # The bug causes this to silently pass and rewrite the lock file with correct checksums assert_raise Mix.Error, ~r/Registry checksum mismatch against lock/, fn -> Mix.Tasks.Deps.Get.run([]) end end defp invalid_checksum("0" rest), do: "1" rest defp invalid_checksum(>, rest: rest), do: "0" rest ```