fix(release): rebuilds must run at the tag ref — keyless identity integrity - #429
Conversation
) Cosign's keyless identity embeds the RUN's ref. workflow_dispatch took an inputs.ref and could build a tag from a branch run, publishing signatures (@refs/heads/...) that the tag-anchored installers reject on every customer machine. inputs.ref removed; dispatch runs now hard-fail unless started at a v* tag ref; rebuild paths = rerun the tag run or dispatch at the tag. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
👋 Heads-up — Code review queue is at 45 / 30 Above the WIP limit. The team convention is to review existing PRs before opening new work. Open PRs currently in Code review (oldest first):
Pull from review before opening new work. (This is a nudge from the kanban WIP check, not a block.) |
saadqbal
left a comment
There was a problem hiding this comment.
Nice, tight fix 👍 The tag-ref guard lines up with the installers' @refs/tags/v.* anchor, and needs: release means publish can't run when a branch dispatch trips the guard — so all signing runs stay at a tag ref. One non-blocking hardening nit inline. Minor thought: a job-level if: (or a tiny pre-flight job that release needs) would reject a misdirected branch dispatch once, instead of spinning up all 8 matrix legs to each fail the guard.
saadqbal
left a comment
There was a problem hiding this comment.
Nice, careful fix — constrains the dispatch ref at the root instead of band-aiding the installers, and the comments make the keyless-identity reasoning easy to follow 👍 Verified the premise holds against develop (installers + header verify block both trust @refs/tags/v.*). One optional non-blocker inline.
Guard moved out of the 8-way matrix into a tiny job that release needs: a branch-misdispatch now fails once in seconds instead of burning eight runners' setup. Refs passed via env, never interpolated -- git permits $/backticks in tag names, so a crafted v* tag would otherwise execute on the runner (R8, same rule as the client installer workflows). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
@saadqbal both nits implemented (pre-flight guard job + env-passed refs, in-matrix guard removed) — the new commit dismissed your approval per stale-review policy; quick re-tick when you have a second and Lukas lands it. |
The one step this PR's hardening missed: it still did REF="${{ github.ref_name }}",
interpolating an attacker-controllable tag name straight into the shell, so a
crafted v* tag with backticks or $() would execute on the publish runner
before the release is created. Now passed as env REF_NAME and read as $REF_NAME,
matching the guard and version steps.
|
@saadqbal you're right — that step was the one the earlier hardening pass missed, and Bugbot flagged the same line. Fixed in b201c11.
- name: Determine release tag
id: tag
env:
REF_NAME: ${{ github.ref_name }}
run: |
REF="$REF_NAME"So the tag ref is passed through the environment, never interpolated into the script — a crafted Both threads resolved. |
|
bugbot run |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit b201c11. Configure here.
Both Bugbot findings on promotion #428, confirmed real as one defect:
workflow_dispatchacceptedinputs.refso a tag could be rebuilt from a branch run — cosign embeds the run's ref in the keyless identity, producing@refs/heads/...signatures that the tag-anchored installers (correctly) reject on every customer machine.Fix:
inputs.refremoved; dispatch runs hard-fail unless started at av*tag ref; supported rebuild paths aregh run rerunof the tag run or dispatching at the tag (Actions → Run workflow → select the tag). Installers stay untouched — their anchor is right.Release note: this fix lands on develop → rides the next cycle (v0.10.2). Shipping v0.10.1 with the hazard is internal-only (it bites release-managers doing branch-dispatched rebuilds, never normal installs) — ops rule until then: rebuild only via rerun/tag-ref dispatch.
🤖 Generated with Claude Code
Note
Medium Risk
Changes only CI release plumbing but directly affects how signed artifacts are published; misconfiguration could still block rebuilds until ops use tag-ref dispatch or rerun.
Overview
Fixes release rebuilds that produced cosign identities installers reject. Manual
workflow_dispatchno longer accepts aninputs.reftag string, so a run started on a branch cannot rebuild a release while embedding@refs/heads/...in keyless signatures. Rebuilds must be triggered at thev*tag (Actions → Run workflow on the tag) or viagh run rerunon an existing tag run; checkouts and version/tag resolution now usegithub.refonly.Adds a lightweight
guardjob that fails branch dispatches before the build matrix starts, with docs in the workflow header explaining why cosign’s run ref must match@refs/tags/v.*.Hardens runner scripts (R8): version and publish tag steps pass
github.ref_namethroughREF_NAMEenv instead of interpolating ref strings into shell, avoiding command injection from malicious tag names.Reviewed by Cursor Bugbot for commit b201c11. Bugbot is set up for automated code reviews on this repo. Configure here.