Verify sccache downloads by default #8

Merged
stephen merged 1 commit from verify-sccache-downloads into main 2026-07-05 19:56:46 +00:00
Owner

Fixes the row-13 download integrity finding.

Confirmed against current main before patching. The installer documented checksum verification as opt-in:

#   SCCACHE_VERIFY_CHECKSUM   "true" to verify the .sha256 sidecar
#   SCCACHE_SHA256            optional pinned tarball SHA-256 digest

It downloaded the tarball before any verification:

echo "Downloading ${tar_url}"
curl -fsSL --retry 5 --retry-delay 2 --retry-connrefused \
  -o "${tmp}/${tarball}" "$tar_url"

And the sidecar verification path was gated only by SCCACHE_VERIFY_CHECKSUM=true, otherwise falling back to transport trust:

if [ "${SCCACHE_VERIFY_CHECKSUM}" = "true" ]; then
  echo "Verifying checksum against ${sha_url}"
  curl -fsSL --retry 5 --retry-delay 2 --retry-connrefused \
    -o "${tmp}/${tarball}.sha256" "$sha_url"
  ...
else
  echo "checksum verification disabled; trusting transport only" >&2
fi

Changes:

  • default verification is enforced in the script with SCCACHE_VERIFY_CHECKSUM defaulting to true
  • adds pinned SHA-256 table for supported v0.15.0 Linux/macOS assets
  • fails closed when no sidecar or pin verifies the tarball
  • keeps only explicit verify-checksum: false as an insecure escape hatch with a loud warning
  • keeps explicit sha256 enforced even when verification is disabled
  • updates README/action/security docs to match the actual integrity behavior
  • adds offline regressions for good hash, bad hash, built-in pin mismatch, missing sidecar/no pin, and explicit opt-out warning

Local verification:

  • shellcheck scripts/install.sh scripts/install-hooks.sh tests/run.sh tests/checksum-mismatch.sh .githooks/pre-commit .githooks/commit-msg
  • make test
  • make test-integration

Local note: make all cannot complete in this environment because shfmt and actionlint are not installed; shellcheck and both test targets pass.

Fixes the row-13 download integrity finding. Confirmed against current main before patching. The installer documented checksum verification as opt-in: ```sh # SCCACHE_VERIFY_CHECKSUM "true" to verify the .sha256 sidecar # SCCACHE_SHA256 optional pinned tarball SHA-256 digest ``` It downloaded the tarball before any verification: ```sh echo "Downloading ${tar_url}" curl -fsSL --retry 5 --retry-delay 2 --retry-connrefused \ -o "${tmp}/${tarball}" "$tar_url" ``` And the sidecar verification path was gated only by `SCCACHE_VERIFY_CHECKSUM=true`, otherwise falling back to transport trust: ```sh if [ "${SCCACHE_VERIFY_CHECKSUM}" = "true" ]; then echo "Verifying checksum against ${sha_url}" curl -fsSL --retry 5 --retry-delay 2 --retry-connrefused \ -o "${tmp}/${tarball}.sha256" "$sha_url" ... else echo "checksum verification disabled; trusting transport only" >&2 fi ``` Changes: - default verification is enforced in the script with `SCCACHE_VERIFY_CHECKSUM` defaulting to true - adds pinned SHA-256 table for supported `v0.15.0` Linux/macOS assets - fails closed when no sidecar or pin verifies the tarball - keeps only explicit `verify-checksum: false` as an insecure escape hatch with a loud warning - keeps explicit `sha256` enforced even when verification is disabled - updates README/action/security docs to match the actual integrity behavior - adds offline regressions for good hash, bad hash, built-in pin mismatch, missing sidecar/no pin, and explicit opt-out warning Local verification: - `shellcheck scripts/install.sh scripts/install-hooks.sh tests/run.sh tests/checksum-mismatch.sh .githooks/pre-commit .githooks/commit-msg` - `make test` - `make test-integration` Local note: `make all` cannot complete in this environment because `shfmt` and `actionlint` are not installed; `shellcheck` and both test targets pass.
Verify sccache downloads by default
All checks were successful
test / integration (pull_request) Successful in 5s
test / unit (pull_request) Successful in 8s
test / install (v0.14.0) (pull_request) Successful in 7s
test / install (v0.15.0) (pull_request) Successful in 6s
test / install-without-v-prefix (pull_request) Successful in 5s
test / reinstall-on-version-change (pull_request) Successful in 6s
5d7f7baf13
Author
Owner

Adversarial review: APPROVE

Reviewed at head 5d7f7ba against main. I wrote the row-13 finding, so I went looking for a cosmetic fix; this is a real one. All five requirements hold, verified by reading scripts/install.sh, running the suite, and exercising the real download path.

(1) On by default, verified before execution. verify_checksum="${SCCACHE_VERIFY_CHECKSUM:-true}" (install.sh:25) and action.yml wires SCCACHE_VERIFY_CHECKSUM: ${{ inputs.verify-checksum }} with default: 'true'. Only the exact string false disables it; any other value verifies (fail-safe). Ordering is correct: download (:104) → verify (:119-184) → tar -xzf (:186) → install (:196) → sccache --version (:214). The binary is never extracted or executed before the digest is checked.

(2) Fails closed with no verification source. Sidecar fetch failure with no built-in pin and no explicit sha256 exits 1 (:169-171), and a catch-all if [ "$verified" != "true" ] exits 1 (:180-183). The mirror path (download-base-url) also fails closed: the built-in pin is skipped for a mirror, so a mirror serving neither sidecar nor sha256 hits :169-171. Covered by new tests 18 and 19.

(3) The pins are real, not theater. All four v0.15.0 pins match the actual mozilla/sccache release .sha256 sidecars, fetched live:

x86_64-unknown-linux-musl   782d2b5d…709e  MATCH
aarch64-unknown-linux-musl  3a6a3712…d8f8  MATCH
x86_64-apple-darwin         f8da93e0…67db  MATCH
aarch64-apple-darwin        430ef7b5…c6e9  MATCH

The pin-table keys (x86_64-unknown-linux-musl, etc.) exactly match the triples install.sh computes (:76-86), so the pin actually fires on the default asset rather than silently missing.

(4) Opt-out is explicit and loud. Disabling requires verify-checksum: false exactly; install.sh:152 prints SECURITY WARNING: checksum verification explicitly disabled... to stderr, and an explicit sha256 is still enforced even then (:153-155). action.yml documents it as an "explicit insecure escape hatch." Test 21 asserts the warning.

(5) Docs match reality. README, SECURITY.md, and action.yml all now describe "built-in release pins and the upstream sidecar by default," and SECURITY.md correctly calls the built-in pin the stronger protection (the sidecar shares the tarball's origin). Consistent with the code.

Evidence

  • bash tests/run.sh: 30/30 pass, including the two new fail-closed cases and the escape-hatch warning.
  • Live, with the pre-installed sccache hidden from PATH so the download path actually runs:
    • Real download + wrong explicit sha256 → exit 1, sha256 input mismatch, nothing installed (actual hash was the genuine 782d…).
    • Real download, default settings → pinned sha256 ok + checksum sidecar ok, verified binary installed.
    • Coordinated-swap test (a shimmed curl serving a poisoned tarball and a matching poisoned sidecar on the default github path): rejected with pinned sha256 mismatch, poisoned binary not installed. This is exactly the sidecar-is-TOFU-from-the-same-origin gap row 13 raised, and the built-in pin (shipped in git, not fetched) defeats it.

Non-blocking notes (follow-ups, not merge blockers)

  • The pin table covers v0.15.0 only. Bumping the version input to an unlisted release silently downgrades to sidecar-only on the github path (still fails closed if the sidecar is absent, but a coordinated release-page swap on that version would not be caught). Worth extending the table when the default version bumps, or a comment noting pins track the default asset.
  • For a mirror (download-base-url), the pin is intentionally skipped, so mirror integrity rests on the mirror's sidecar or an explicit sha256. Reasonable, and already documented in SECURITY.md.

Fix is real and complete. APPROVE for merge.

## Adversarial review: APPROVE Reviewed at head `5d7f7ba` against `main`. I wrote the row-13 finding, so I went looking for a cosmetic fix; this is a real one. All five requirements hold, verified by reading `scripts/install.sh`, running the suite, and exercising the real download path. **(1) On by default, verified before execution.** `verify_checksum="${SCCACHE_VERIFY_CHECKSUM:-true}"` (install.sh:25) and `action.yml` wires `SCCACHE_VERIFY_CHECKSUM: ${{ inputs.verify-checksum }}` with `default: 'true'`. Only the exact string `false` disables it; any other value verifies (fail-safe). Ordering is correct: download (`:104`) → verify (`:119-184`) → `tar -xzf` (`:186`) → install (`:196`) → `sccache --version` (`:214`). The binary is never extracted or executed before the digest is checked. **(2) Fails closed with no verification source.** Sidecar fetch failure with no built-in pin and no explicit `sha256` exits 1 (`:169-171`), and a catch-all `if [ "$verified" != "true" ]` exits 1 (`:180-183`). The mirror path (`download-base-url`) also fails closed: the built-in pin is skipped for a mirror, so a mirror serving neither sidecar nor `sha256` hits `:169-171`. Covered by new tests 18 and 19. **(3) The pins are real, not theater.** All four `v0.15.0` pins match the actual `mozilla/sccache` release `.sha256` sidecars, fetched live: ``` x86_64-unknown-linux-musl 782d2b5d…709e MATCH aarch64-unknown-linux-musl 3a6a3712…d8f8 MATCH x86_64-apple-darwin f8da93e0…67db MATCH aarch64-apple-darwin 430ef7b5…c6e9 MATCH ``` The pin-table keys (`x86_64-unknown-linux-musl`, etc.) exactly match the triples `install.sh` computes (`:76-86`), so the pin actually fires on the default asset rather than silently missing. **(4) Opt-out is explicit and loud.** Disabling requires `verify-checksum: false` exactly; `install.sh:152` prints `SECURITY WARNING: checksum verification explicitly disabled...` to stderr, and an explicit `sha256` is still enforced even then (`:153-155`). `action.yml` documents it as an "explicit insecure escape hatch." Test 21 asserts the warning. **(5) Docs match reality.** README, SECURITY.md, and `action.yml` all now describe "built-in release pins and the upstream sidecar by default," and SECURITY.md correctly calls the built-in pin the stronger protection (the sidecar shares the tarball's origin). Consistent with the code. ### Evidence - `bash tests/run.sh`: 30/30 pass, including the two new fail-closed cases and the escape-hatch warning. - Live, with the pre-installed sccache hidden from `PATH` so the download path actually runs: - Real download + wrong explicit `sha256` → exit 1, `sha256 input mismatch`, nothing installed (actual hash was the genuine `782d…`). - Real download, default settings → `pinned sha256 ok` + `checksum sidecar ok`, verified binary installed. - **Coordinated-swap test** (a shimmed `curl` serving a poisoned tarball *and* a matching poisoned sidecar on the default github path): rejected with `pinned sha256 mismatch`, poisoned binary not installed. This is exactly the sidecar-is-TOFU-from-the-same-origin gap row 13 raised, and the built-in pin (shipped in git, not fetched) defeats it. ### Non-blocking notes (follow-ups, not merge blockers) - The pin table covers `v0.15.0` only. Bumping the `version` input to an unlisted release silently downgrades to sidecar-only on the github path (still fails closed if the sidecar is absent, but a coordinated release-page swap on that version would not be caught). Worth extending the table when the default version bumps, or a comment noting pins track the default asset. - For a mirror (`download-base-url`), the pin is intentionally skipped, so mirror integrity rests on the mirror's sidecar or an explicit `sha256`. Reasonable, and already documented in SECURITY.md. Fix is real and complete. **APPROVE for merge.**
Sign in to join this conversation.
No description provided.