fix(cache): bound verified compressed archive reads before allocation
Issue
Closes #196 only after successful authorized merge and post-main qualification. Canonical main currently limits registry and local-mirror acquisition to 128 MiB compressed archives, but PackageCache::read_verified previously used unbounded fs::read on the on-disk cache object before checking its SHA-256. A locally replaced/corrupted cache object could force unbounded allocation and reading. This is a local resource-exhaustion risk, not a claim of remote exploitability.
Implementation
- Reuse canonical
source::MAX_COMPRESSED_PACKAGE_ARCHIVE_BYTES(128 MiB) inPackageCache::read_verified, routing through the existing bounded verifier. - In the bounded reader, clamp caller-provided larger limits to that ceiling, check file metadata length before allocating, and preserve
take(limit + 1)+ post-read length validation to catch file growth between metadata/read. Keep SHA-256 validation of exact consumed bytes. - Fail closed for oversized
PackageCache::putinputs before writing a new cache object. Keep missing/digest classification, cache path layout and resolver semantics unchanged. - Add deterministic boundary tests for exact/+1 sizes and sparse 128 MiB + 1 on-disk files. Sparse tests do not allocate 128 MiB in memory and assert
InvalidRequest, not a late digest-mismatch report.
Governance and evidence
No AF-02 protected files, FHIR oracle, lockfile, GitHub Actions workflow, required check, dependency, donor or clinical contract is modified. No paid model or cloud compute is required. This PR is independent of #194, and historical issue #100 remains open.
Before merging: exact-head Rust formatting + unit/workspace tests, full GitHub required checks, independent human Code Owner approval, last-push review, thread resolution, normal merge commit, then post-main verification. A green bot or author comment cannot substitute for independent approval.
Base observed f82565cca917d119e1c774b2c470e2ac20e0d6dd; first head fee0b917fc28b4def5d38e99969efdc2fb3ff836.
Summary by cubic
Fixes a local resource-exhaustion risk in PackageCache::read_verified. Reads of on-disk cache objects are now capped at 128 MiB, matching the limit used for registry and local-mirror acquisition, so a replaced or corrupted cache file can no longer force unbounded allocation before SHA-256 validation.
- Checks file metadata length before allocating, then re-checks after the read to catch growth between the two operations.
- Clamps caller-supplied larger limits to the 128 MiB ceiling.
- Rejects oversized
PackageCache::putinputs before writing a cache object. - Adds boundary tests for exact-size, one-byte-over, and sparse oversized files.