Commit 6328c38
fix(ci): verify execlog2csv against a pinned sha256 (#11310)
## What
The shared bazel composite action downloaded the `execlog2csv` zip from
`github.com/dfinity/execlog2csv` release assets, unzipped it, installed
it to `/usr/local/bin` with `sudo` and ran it — trusting nothing but the
URL.
This pins the sha256 of each release zip in this repo and checks the
download **before** unpacking or executing any of it, following the
pattern already used for bazelisk in
[`ci/container/Dockerfile`](https://github.com/dfinity/ic/blob/master/ci/container/Dockerfile#L34-L36).
## Why
GitHub release assets are mutable under an existing tag — the API
reports `"immutable": false` for `v0.0.2` — so anyone with release
access to that separate, low-profile repo got code execution inside
every ic CI job that enables execlogs. That includes `bazel-test-all` on
release builds, where the binary runs *after*
`configure-aws-credentials` has exported the artifact-upload role into
the job env and while `CF_AWS_ACCESS_KEY_ID`/`CF_AWS_SECRET_ACCESS_KEY`
are present.
The hashes come from the release's `execlog2csv_0.0.2_SHA256SUMS` asset.
Verifying against that asset *at runtime* would be worthless: it is a
mutable asset in the same release, so whoever can swap the zip can swap
the sums file alongside it. The hashes have to live here, in a reviewed
tree.
## Notes on the implementation
- A `case` rather than `declare -A`: macOS ships bash 3.2, which has no
associative arrays, and this script supports darwin.
- `shasum -a 256` fallback for the same reason — macOS has no coreutils
`sha256sum`.
- `curl -SLO` → `-fSLO`, so an HTTP error page fails at the real cause
instead of as a hash mismatch.
- All four os/arch combos the script can construct are pinned; an
unpinned combo exits 1 rather than silently skipping verification.
- Pinned version `0.0.2` is already the latest release, so no version
bump was needed.
## Fails closed, and that blocks release uploads
The step runs under GitHub's `shell: bash` default (`-eo pipefail`), so
a mismatch aborts the step and fails the job. In `bazel-test-all` the
composite action's first invocation completes *before* the job's `Upload
artifacts` step, which has no `if: always()` — so on a release build a
hash mismatch also stops publication to `download.dfinity.systems`.
This is not a behavioural regression: a failing `curl` or `unzip`
already fails the step today.
## Verification
Ran against the live upstream release:
- **Positive** — step runs end-to-end, logs
`execlog2csv_0.0.2_linux_amd64.zip: OK`, binary installs and `--help`
works.
- **Negative** — one flipped hex char → `WARNING: 1 computed checksum
did NOT match`, exit 1, and no `execlog2csv_v0.0.2` extracted,
confirming the check precedes `unzip`.
- **Unpinned platform** — forcing `freebsd_amd64` prints `no pinned
sha256 for 'freebsd_amd64'` and exits 1.
- **darwin `shasum` branch** — OK/exit 0 on the real hash, FAILED/exit 1
on a corrupted one.
- All four pinned hashes re-checked programmatically against upstream's
`SHA256SUMS` — 4/4 match.
CI itself exercises this in all three execlog-enabled invocations:
`Bazel Test All` (Run Bazel Commands + Run Tests) and `Build IC`.
## Scope / residual risk
- A pin authenticates bytes, not intent. On `pull_request` events the
composite action comes from the PR tree, so a PR author can edit the
hash alongside the URL; this protects protected-branch and release
builds, where the tree is reviewed.
- Defence-in-depth follow-up outside this repo: ask
`dfinity/execlog2csv` to publish **immutable releases** and
build-provenance attestations, then verify with `gh attestation verify`.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>1 parent 96c981b commit 6328c38
1 file changed
Lines changed: 30 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
120 | 120 | | |
121 | 121 | | |
122 | 122 | | |
123 | | - | |
| 123 | + | |
| 124 | + | |
124 | 125 | | |
125 | 126 | | |
126 | 127 | | |
| |||
132 | 133 | | |
133 | 134 | | |
134 | 135 | | |
135 | | - | |
| 136 | + | |
136 | 137 | | |
137 | 138 | | |
138 | 139 | | |
139 | 140 | | |
140 | 141 | | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
141 | 160 | | |
142 | 161 | | |
143 | | - | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
144 | 171 | | |
145 | 172 | | |
146 | 173 | | |
| |||
0 commit comments