From 7e320052fd9cc88c7d5cce2c221c00b0ba6c8605 Mon Sep 17 00:00:00 2001 From: Dmitrii Creed Date: Mon, 18 May 2026 20:48:58 +0400 Subject: [PATCH] hotfix(sc.sh): drop invalid --yes flag on cosign verify-blob MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PRODUCTION OUTAGE FIX. Every `curl -sSL https://dist.simple-container.com/sc.sh | bash` since PR #264 (Phase 2c) shipped has been failing the signature verify step with no useful error surfaced. Reported by integrail/everworker agents stuck on v2026.5.18. ## Root cause PR #264 introduced `verify_sc_tarball` which calls: cosign verify-blob --yes --bundle ... `--yes` is a `cosign sign-blob` flag (skip interactive Fulcio confirmation) but is NOT defined on `cosign verify-blob`. Every cosign version returns: Error: unknown flag: --yes The script's `>/dev/null 2>&1` swallowed that error so users saw a generic "Signature verification FAILED" message that pointed at tampering / CDN compromise / identity rotation — all wrong. Empirically verified: cosign verify-blob --yes ... t.tar.gz # Error: unknown flag --yes cosign verify-blob ... t.tar.gz # Verified OK Cert identity on the actual bundle MATCHES sc.sh's expected regex: SAN URI: https://github.com/simple-container-com/api/.github/workflows/push.yaml@refs/heads/main OIDC: https://token.actions.githubusercontent.com So no signing-side change needed. Only the verify call was malformed. ## Fix 1. Drop `--yes` from the `cosign verify-blob` invocation in sc.sh. 2. Capture cosign's stderr into a variable (instead of discarding via /dev/null) so future verify failures surface the real cosign error to the user instead of a generic blame-the-CDN message. ## Verified Patched function runs against the actual broken v2026.5.18 artifact on dist.simple-container.com and returns "Verified OK". Smoke tested locally end-to-end before committing. ## Republish plan Production releases v2026.5.16 / .17 / .18 / .19 all carry the buggy sc.sh (the script is bundled with each release tarball). The fix needs a new prod release to land at dist; no need to re-sign existing artifacts — their bundles are valid, only the consumer code was broken. Bumping to v2026.5.20 (next prod release after this hotfix merges) is sufficient to unblock downstream consumers (Integrail/EverWorker). Signed-off-by: Dmitrii Creed --- sc.sh | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/sc.sh b/sc.sh index 76f9afbf..b7f72358 100755 --- a/sc.sh +++ b/sc.sh @@ -434,13 +434,23 @@ verify_sc_tarball() { # the only workflow allowed to publish tarballs to dist. Staging / # preview tarballs do not land at dist.simple-container.com, so a # single anchored regex suffices here. Mirror this in SECURITY.md. - if ! COSIGN_EXPERIMENTAL=1 cosign verify-blob --yes \ + # + # IMPORTANT: do NOT pass --yes here. cosign 2.x only accepts --yes on + # sign-blob (skip interactive confirmation); on verify-blob it errors + # out with "unknown flag: --yes" — which is what broke every install + # after Phase 2c shipped. Capture cosign's stderr (don't /dev/null it) + # so future failures surface the real error instead of a generic + # message. + local cosign_err + if ! cosign_err=$(COSIGN_EXPERIMENTAL=1 cosign verify-blob \ --bundle "$bundle_path" \ --certificate-identity-regexp '^https://github\.com/simple-container-com/api/\.github/workflows/push\.yaml@refs/heads/main$' \ --certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \ - "$tarball_path" >/dev/null 2>&1; then + "$tarball_path" 2>&1); then echo "❌" echo "❌ Signature verification FAILED for $tarball_path" + echo " cosign output:" + echo "$cosign_err" | sed 's/^/ /' echo " The tarball does not bear a valid signature from the SC" echo " production publish workflow. This could mean: tarball was" echo " tampered in transit, CDN was compromised, or the signing"