Skip to content

alpine: hash only the bytes read when computing the control.tar.gz digest - #2908

Merged
bobcallaway merged 1 commit into
sigstore:mainfrom
sueun-dev:fix-alpine-partial-read-hash
Aug 3, 2026
Merged

bobcallaway merged 1 commit into
sigstore:mainfrom
sueun-dev:fix-alpine-partial-read-hash

Conversation

@sueun-dev

Copy link
Copy Markdown
Contributor

sha1Reader.Read hashes the whole read buffer instead of the part that was actually filled:

n, err := s.r.Read(p)
if err == nil && n > 0 && s.addToHash {
    s.hasher.Write(p)   // hashes p[:len(p)], not p[:n]
}

When the underlying read returns fewer bytes than requested (n < len(p)), the stale tail of p gets folded into the SHA1. That digest is the value the package signature is checked against in VerifySignature, so once it is off a validly signed package fails verification.

It doesn't show up in the existing test because Package.Unmarshal is handed an *os.File, and reads on a regular file fill the buffer. A reader that can return short reads hits it — a network stream / http.Response.Body, or bufio at a refill boundary. gzip reads the compressed stream in chunks larger than one byte, so a short read there feeds stale bytes into the digest.

The fix is Write(p[:n]).

I added TestAlpinePackagePartialReads: it unmarshals the existing signed fixture through a reader that returns one byte per call, then checks the control digest matches the whole-file read and the signature still verifies. Before the change the two digests differ and verification returns crypto/rsa: verification error; after it, they match.

go test ./pkg/types/alpine/...

…gest

sha1Reader.Read hashed the whole buffer p instead of p[:n], so when the
underlying reader returns a short read the stale tail of p is folded into
the control.tar.gz SHA1 that the package signature is verified against,
making a validly signed package fail verification.

Added TestAlpinePackagePartialReads, which unmarshals the existing signed
fixture through a reader that returns one byte per call and checks the
digest matches the whole-file read and the signature still verifies.

Signed-off-by: sueun-dev <sueun.dev@gmail.com>
@sueun-dev
sueun-dev requested a review from a team as a code owner August 3, 2026 08:48
@codecov

codecov Bot commented Aug 3, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 27.69%. Comparing base (488eb97) to head (69bfd7f).
⚠️ Report is 743 commits behind head on main.

Additional details and impacted files
@@             Coverage Diff             @@
##             main    #2908       +/-   ##
===========================================
- Coverage   66.46%   27.69%   -38.77%     
===========================================
  Files          92      192      +100     
  Lines        9258    20344    +11086     
===========================================
- Hits         6153     5635      -518     
- Misses       2359    13842    +11483     
- Partials      746      867      +121     
Flag Coverage Δ
e2etests 49.86% <100.00%> (+2.30%) ⬆️
unittests 19.05% <100.00%> (-28.64%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@bobcallaway
bobcallaway merged commit dfe5a1c into sigstore:main Aug 3, 2026
17 checks passed
stgrace pushed a commit to stgrace/rekor that referenced this pull request Aug 22, 2026
…gest (sigstore#2908)

sha1Reader.Read hashed the whole buffer p instead of p[:n], so when the
underlying reader returns a short read the stale tail of p is folded into
the control.tar.gz SHA1 that the package signature is verified against,
making a validly signed package fail verification.

Added TestAlpinePackagePartialReads, which unmarshals the existing signed
fixture through a reader that returns one byte per call and checks the
digest matches the whole-file read and the signature still verifies.

Signed-off-by: sueun-dev <sueun.dev@gmail.com>
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.

2 participants