context: cap TLS reads during zip import#7017
Conversation
Signed-off-by: Rage Lopez <VrtxOmega@pm.me>
| if l.N == 0 { | ||
| return 0, io.EOF | ||
| } |
There was a problem hiding this comment.
Curious; why was this condition removed?
There was a problem hiding this comment.
Good question — this was intentional to fix a boundary detection gap with chunked reads.
The old early-return at l.N == 0 silently masks data beyond the limit as io.EOF when the underlying reader delivers data in chunks. This is realistic for zip decompression streams that don't deliver all bytes in a single Read() call.
The bug scenario:
// Underlying reader has 5 bytes but delivers them in 2-byte chunks: AB, CD, E
// Limit is 4 bytes
r := &chunkedReader{data: []byte("ABCDE"), chunkSize: 2}
lr := &limitedReader{R: r, N: 4}
data, err := io.ReadAll(lr)
// OLD: reads AB (N=2), reads CD (N=0), next call returns io.EOF
// → ReadAll returns ("ABCD", nil) — SILENT TRUNCATION!
// The 5th byte "E" is never detected.
// NEW: reads AB (N=2), reads CD (N=0), next call probes with 1-byte read,
// gets "E" (N=-1) → returns error
// → ReadAll returns ("ABCD", "read exceeds the defined limit") — CAUGHT!The old code's if l.N == 0 { return 0, io.EOF } tells io.ReadAll "stream ended cleanly" when the underlying reader actually has more data beyond the limit. This is a security concern for the zip bomb fix — if a TLS entry decompresses to exactly 10MB in chunks, the old code returns EOF. If it's 10MB+1 byte delivered as (10MB chunk) + (1 byte chunk), the old code also returns EOF after reading 10MB, silently truncating without error.
The new code removes that early return and probes the underlying reader at the zero-remaining boundary: when N reaches 0, the next read is capped to 1 byte (N+1). If the underlying reader returns data, N goes to -1 and we report the violation. If it returns io.EOF, we propagate it cleanly.
The regression test validates this — the "Tes" (3 bytes, N=2) case catches both implementations via the N+1 cap, but the chunked scenario is where the old code fails.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
|
Two CI checks are failing on the metadata side — both require maintainer action:
All 90 test/lint/build checks pass — just these two gating metadata checks remain. |
- What I did
Applied the existing context-import decompressed read limit to TLS entries in zip context archives.
Fixes #6917
- How I did it
tls/entry reads withlimitedReader, matchingmeta.jsonlimitedReaderso it probes the underlying reader at the zero-remaining boundary and reports data beyond the limit- How to verify it
- Human readable description for the release notes