Raised in review of #57. Two problems, ordered by how live they are.
1. The cargo fallback is unpinned — and it is the only path that runs today
scripts/install-resq.sh prefers a digest-verified GitHub Release asset and falls back to cargo install. But resq-software/crates publishes no resq-cli-v* releases at all, so resolve_tag() returns empty and every invocation lands here:
# install-resq.sh:68 — WANTED_VERSION unset, so no --tag
cargo install --git "https://github.com/resq-software/crates" resq-cli
No --tag, no --rev. So this:
curl -fsSL https://get.resq.software/resq.sh | sh
builds and installs from crates default-branch HEAD at that instant. Unpinned, mutable, unverified — and unlike the asset path, this branch is not gated by RESQ_ALLOW_UNVERIFIED; it is the silent default.
The Worker hands over resq.sh with full chain of custody — pinned commit SHA, SHA-256 verified, fail-closed — and resq.sh then discards that guarantee one hop later. The verified part is the wrapper; the unverified part is the payload.
Worth stating plainly: the digest-verification machinery in that script is not wrong, it is simply unreachable. The bug is that its fallback is weaker than its primary path and nothing says so.
Fix
2. No signatures — verification requires trusting GitHub
Even on the asset path, install-resq.sh fetches the artifact and its SHA256SUMS from the same GitHub release. That detects corruption in transit; it does not detect a compromised or coerced release. Both sides come from one origin, so the digest proves internal consistency, not provenance. (The script's own awk comment already mentions .sig files it never checks.)
Same limitation on get.resq.software: pinned digests ship with the deploy rather than the response, which defeats a tampering CDN — but there is still no key a third party can verify against offline.
Recommendation: Sigstore/cosign
The org already ships @resq-systems/types to npm with provenance: true, which is Sigstore-backed — so this is an extension of tooling already in use, not a new dependency.
minisign is the smaller alternative — one key, one 100-line dependency, trivially verifiable offline — but it needs private-key custody and rotation, which keyless Sigstore avoids. Recommend cosign; minisign only if a reviewer specifically wants an air-gapped path with no OIDC.
Why this is worth doing before it is asked for
The current answer to "how do I verify what you shipped" is "trust GitHub, and trust our CDN." For public-safety and DoD SBIR diligence the expected answer is "here is the signature and the public identity, verify it offline without trusting us." That is a design choice now and a finding later.
Concretely, the property to reach: a reviewer with no network access to us, holding only the artifact and our public identity, can prove the binary came from our release pipeline.
Scope note
Spans two repos: crates publishes and signs; dev verifies in install-resq.sh. Item 1 is the live exposure and should not wait for item 2 — pinning the fallback is a few lines and closes an actual hole today.
Raised in review of #57. Two problems, ordered by how live they are.
1. The cargo fallback is unpinned — and it is the only path that runs today
scripts/install-resq.shprefers a digest-verified GitHub Release asset and falls back tocargo install. Butresq-software/cratespublishes noresq-cli-v*releases at all, soresolve_tag()returns empty and every invocation lands here:No
--tag, no--rev. So this:curl -fsSL https://get.resq.software/resq.sh | shbuilds and installs from
cratesdefault-branch HEAD at that instant. Unpinned, mutable, unverified — and unlike the asset path, this branch is not gated byRESQ_ALLOW_UNVERIFIED; it is the silent default.The Worker hands over
resq.shwith full chain of custody — pinned commit SHA, SHA-256 verified, fail-closed — andresq.shthen discards that guarantee one hop later. The verified part is the wrapper; the unverified part is the payload.Worth stating plainly: the digest-verification machinery in that script is not wrong, it is simply unreachable. The bug is that its fallback is weaker than its primary path and nothing says so.
Fix
resq-cli-v*releases fromcrateswith per-target assets +SHA256SUMS, which makes the existing verified path livecargo install --git <repo> --rev <40-hex> resq-cli, never a bare branch buildRESQ_ALLOW_UNVERIFIED=1when it cannot be pinned, matching how every other unverifiable branch in this repo already behaves2. No signatures — verification requires trusting GitHub
Even on the asset path,
install-resq.shfetches the artifact and itsSHA256SUMSfrom the same GitHub release. That detects corruption in transit; it does not detect a compromised or coerced release. Both sides come from one origin, so the digest proves internal consistency, not provenance. (The script's own awk comment already mentions.sigfiles it never checks.)Same limitation on
get.resq.software: pinned digests ship with the deploy rather than the response, which defeats a tampering CDN — but there is still no key a third party can verify against offline.Recommendation: Sigstore/cosign
The org already ships
@resq-systems/typesto npm withprovenance: true, which is Sigstore-backed — so this is an extension of tooling already in use, not a new dependency.cosign sign-blobeach release asset in CI; publish.sig+.pemalongside--certificate-identity= the release workflow,--certificate-oidc-issuer= GitHub Actions), so there is no long-lived private key to holdattestations: writeandactions/attest-build-provenancefor SLSA provenance on the binariesinstall-resq.shto verify whencosignis present, and to say clearly what was and was not verified when it is absent — fail closed unlessRESQ_ALLOW_UNVERIFIED=1, matching the existing conventionminisignis the smaller alternative — one key, one 100-line dependency, trivially verifiable offline — but it needs private-key custody and rotation, which keyless Sigstore avoids. Recommend cosign; minisign only if a reviewer specifically wants an air-gapped path with no OIDC.Why this is worth doing before it is asked for
The current answer to "how do I verify what you shipped" is "trust GitHub, and trust our CDN." For public-safety and DoD SBIR diligence the expected answer is "here is the signature and the public identity, verify it offline without trusting us." That is a design choice now and a finding later.
Concretely, the property to reach: a reviewer with no network access to us, holding only the artifact and our public identity, can prove the binary came from our release pipeline.
Scope note
Spans two repos:
cratespublishes and signs;devverifies ininstall-resq.sh. Item 1 is the live exposure and should not wait for item 2 — pinning the fallback is a few lines and closes an actual hole today.