M6: Fail closed on missing/unfetchable SHA256SUMS in the auto-updater #242

Merged
KofTwentyTwo merged 1 commits from story/m6-updater-fail-closed into dev 2026-07-30 17:55:59 +00:00
KofTwentyTwo commented 2026-07-30 17:55:18 +00:00 (Migrated from github.com)

Closes the fail-open paths in UpdateEngine::download_and_verify.

Before: returned the downloaded archive unverified when (1) the release had no SHA256SUMS.txt asset (checksum_url == None), or (2) fetching the sums file returned a non-2xx status — both silently fell through to Ok(archive_bytes).

After: the only path to Ok is an exact SHA-256 match. Absent asset, non-success fetch, filename-not-found, and hash mismatch all return Err. New distinct UpdateError::ChecksumUnavailable variant separates 'no asset / fetch failed' from 'filename not found in sums file'.

Tests (wiremock, no live network): download_and_verify_fails_closed_without_checksum_asset, _on_sums_fetch_error, _on_hash_mismatch, _succeeds_on_matching_checksum.

crates/nunciod/src/main.rs's autonomous-update gate (AUTO_UPDATE_ENV_VAR) is untouched and remains off by default. No GPG/minisign signature verification added (out of scope). Gate green: fmt/clippy(-D warnings)/test-all, 0 ignored; update:: 11/11.

Refs #202

Closes the fail-open paths in `UpdateEngine::download_and_verify`. **Before:** returned the downloaded archive unverified when (1) the release had no `SHA256SUMS.txt` asset (`checksum_url == None`), or (2) fetching the sums file returned a non-2xx status — both silently fell through to `Ok(archive_bytes)`. **After:** the only path to `Ok` is an exact SHA-256 match. Absent asset, non-success fetch, filename-not-found, and hash mismatch all return `Err`. New distinct `UpdateError::ChecksumUnavailable` variant separates 'no asset / fetch failed' from 'filename not found in sums file'. **Tests (wiremock, no live network):** `download_and_verify_fails_closed_without_checksum_asset`, `_on_sums_fetch_error`, `_on_hash_mismatch`, `_succeeds_on_matching_checksum`. `crates/nunciod/src/main.rs`'s autonomous-update gate (`AUTO_UPDATE_ENV_VAR`) is untouched and remains off by default. No GPG/minisign signature verification added (out of scope). Gate green: fmt/clippy(-D warnings)/test-all, 0 ignored; `update::` 11/11. Refs #202
Sign in to join this conversation.