Skip to content

Add -verify-storage to purge checksum-mismatched modules from storage (#2145)#2146

Merged
matt0x6F merged 5 commits into
mainfrom
matt/sleepy-boyd-4927b0
Jul 18, 2026
Merged

Add -verify-storage to purge checksum-mismatched modules from storage (#2145)#2146
matt0x6F merged 5 commits into
mainfrom
matt/sleepy-boyd-4927b0

Conversation

@matt0x6F

@matt0x6F matt0x6F commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

What is the problem I am trying to address?

Athens builds module zips on a cache miss and stores them, then serves the stored copy on every hit after that. So when it builds a zip wrong, the bad copy is stuck — bumping the toolchain doesn't help, because a cache hit never rebuilds. #2145 is a concrete case: Athens releases on Go 1.20.x strip files under nested vendor/ directories (the x/mod/zip bug fixed in Go 1.24), so the stored zip doesn't match sum.golang.org and clients get checksum errors.

How is the fix applied?

This adds a maintenance command to find those zips and evict them so they refetch cleanly:

athens-proxy -verify-storage          # report mismatches, delete nothing
athens-proxy -verify-storage -purge   # delete the mismatches

It's a separate one-shot process that exits without starting the server (same shape as -version), so you run it as a Job or docker run against the same storage the proxy uses.

Decisions I'd like eyes on:

  • It only deletes a version it can prove wrong against the checksum database. That also means it can only ever delete public, refetchable modules; anything it can't verify (private modules, sumdb unreachable) is left alone, and report is the default.
  • Private modules are skipped via the existing NoSumPatterns, before any lookup, so we never send a private module path to sum.golang.org.
  • It checks against the checksum DB, not an upstream proxy, on purpose — an upstream could be serving the same bad bytes.
  • I kept it a flag rather than an always-on request-path check. The bad zips are a fixed set (main is already on a current toolchain), so a one-shot sweep fits; a background verifier would be permanent complexity for a closed problem.

Docs page added at docs/content/configuration/verify-storage.md with an "am I affected?" rundown — short answer, only if you ran ≤ v0.15.1 (Go 1.20.x) into 2025+ and proxied public go >= 1.24 modules with a nested vendor dir.

Tested with unit tests for the lookup, the hash comparison, and the sweep (report/purge/skip/not-in-DB) over an in-memory backend. I also reproduced the bug directly: go1.20.14 vs go1.25 building ginkgo/v2@v2.32.0 produce exactly the two hashes from the issue, differing by the single stripped vendor file.

Left out on purpose (possible follow-ups): verifying private modules (no authoritative source for their hashes) and an automatic self-heal on the request path.

What GitHub issue(s) does this PR fix or close?

Fixes #2145

matt0x6F added 3 commits July 7, 2026 08:37
Compares each stored module zip's h1: hash to the canonical hash from the
configured checksum database. Includes the sumdb lookup oracle, the Poisoned
predicate, and the Sweep driver that skips private (NoSumPatterns) modules
before any lookup and only flags provable mismatches.
Runs the checksum sweep as a one-shot process and exits without starting the
server. -verify-storage reports mismatches; -verify-storage -purge deletes
them. -purge without -verify-storage is a usage error.
@matt0x6F
matt0x6F requested a review from a team as a code owner July 7, 2026 15:38
@matt0x6F matt0x6F self-assigned this Jul 7, 2026
- gosec G104: explicitly ignore f.Close() in hashZipReader's error path
- contextcheck: RunVerify is a one-shot CLI root, so it builds its own
  context instead of taking an inherited one that GetStorage can't thread
@matt0x6F
matt0x6F enabled auto-merge (squash) July 18, 2026 03:13
@matt0x6F
matt0x6F merged commit 64ce676 into main Jul 18, 2026
14 of 16 checks passed
@matt0x6F
matt0x6F deleted the matt/sleepy-boyd-4927b0 branch July 18, 2026 03:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Stale bundled Go toolchain causes false checksum mismatch on modules with a nested vendor/ dir (x/mod/zip, golang/go#37397)

2 participants