Verify a download
Check that a rom-weaver artifact you downloaded - a release archive, an npm package, or a container image - was built by this repository's release workflow. The install scripts run the first check automatically; use this page to verify a file by hand, to check the full signature, or to change how strict the install scripts are. Why the checks are shaped this way is covered in Release provenance.
Verify a file you downloaded by hand
Hash the file and ask GitHub whether this repository's release workflow built exactly those bytes. Nothing needs installing - this is the same check both install scripts run:
file=rom-weaver-linux-x64-gnu.tar.gz
# sha256sum on Linux; macOS ships shasum instead. Probed rather than tried and
# fallen back from: `$(missing | cut)` exits 0, so a fallback keyed on the exit
# status never runs and the digest silently comes out empty.
if command -v sha256sum >/dev/null 2>&1; then
digest=$(sha256sum "$file" | cut -d ' ' -f 1)
else
digest=$(shasum -a 256 "$file" | cut -d ' ' -f 1)
fi
if curl -fsS "https://api.github.com/repos/rom-weaver/rom-weaver/attestations/sha256:$digest?predicate_type=https://slsa.dev/provenance/v1" \
| grep -q '"repository_id"'
then
echo "VERIFIED: built by the rom-weaver release workflow"
else
echo "NOT VERIFIED: no build provenance covers this file" >&2
fi
The PowerShell equivalent:
$file = 'rom-weaver-win32-x64-msvc.tar.gz'
$digest = (Get-FileHash -Path $file -Algorithm SHA256).Hash.ToLower()
$uri = "https://api.github.com/repos/rom-weaver/rom-weaver/attestations/sha256:${digest}" +
'?predicate_type=https://slsa.dev/provenance/v1'
# A repository with no attestations at all answers 404, which Invoke-RestMethod
# raises rather than returns - uncaught, it ends the script before the
# not-verified message it was written for. Unlike the install scripts, this does
# not tell that apart from an unreachable API; both report NOT VERIFIED here.
# The property is checked before it is read because `@($null).Count` is 1, so
# reading a missing one blind would count an unrelated 200 as verified.
$count = 0
try {
$response = Invoke-RestMethod -Uri $uri
if ($response.PSObject.Properties['attestations']) {
$count = @($response.attestations).Count
}
} catch { }
if ($count -gt 0) {
Write-Host 'VERIFIED: built by the rom-weaver release workflow'
} else {
Write-Error 'NOT VERIFIED: no build provenance covers this file'
}
Keep the predicate_type filter: without it the check passes on files the
release workflow never built.
Why the predicate type filter is mandatory
explains what the unfiltered query actually matches.
An asset from a release cut before provenance was added correctly reports NOT VERIFIED - there is no attestation to find. See what build provenance proves.
Check the signature
The queries above trust GitHub's API response over TLS. To check the Sigstore
signature itself - signature, certificate chain, and transparency-log
inclusion - use gh, which must be signed in even for a public repository:
gh attestation verify rom-weaver-linux-x64-gnu.tar.gz --repo rom-weaver/rom-weaver
gh attestation verify oci://ghcr.io/rom-weaver/rom-weaver-cli:latest \
--repo rom-weaver/rom-weaver
npm packages carry their own provenance, verified with:
npm audit signatures
Control the install scripts' check
The install scripts run the digest query against the file they just downloaded. A definite negative stops the install; an unanswered question does not:
| Outcome | Behavior |
|---|---|
| This repository attested these bytes | installs |
| Nothing attested them - empty response or HTTP 404 | refuses |
| The check could not run - offline, rate-limited, 5xx | warns, installs |
Why an unanswered check installs anyway covers the reasoning behind that last row. Every refusal prints the way past it:
curl --proto '=https' --tlsv1.2 -LsSf \
https://raw.githubusercontent.com/rom-weaver/rom-weaver/main/install.sh |
ROM_WEAVER_SKIP_ATTESTATION=1 sh
The assignment belongs on sh, not on curl: putting it at the front of the
pipeline sets it for the download and not for the script that reads the
variable, so the install refuses again.
Going the other way, ROM_WEAVER_REQUIRE_ATTESTATION=1 promotes the
could-not-run warning to a refusal too, so an install that could not be
verified fails rather than proceeding.