Skip to content

[Bug]: v0.2.0 artifacts are signed as refs/heads/main, not refs/tags/v0.2.0 #279

Description

@Marukome0743

Bug Description

The v0.2.0 artifacts are signed with the identity

https://github.com/santosr2/TerraTidy/.github/workflows/release.yml@refs/heads/main

instead of @refs/tags/v0.2.0. Verification that pins the identity to the tag therefore fails for v0.2.0, while it succeeds for v0.2.0-alpha.4.

The documented verification command in docs/site/docs/getting-started/verification.md uses --certificate-identity-regexp 'https://github.com/santosr2/TerraTidy', which matches any ref, so this doesn't show up there.

Steps to Reproduce

$ gh release download v0.2.0 --repo santosr2/TerraTidy -p 'checksums.txt*'
$ cosign verify-blob checksums.txt \
    --bundle checksums.txt.bundle \
    --certificate-identity-regexp '^https://github\.com/santosr2/TerraTidy/\.github/workflows/.+\.ya?ml@refs/tags/\Qv0.2.0\E$' \
    --certificate-oidc-issuer https://token.actions.githubusercontent.com

Reading the identity straight out of the bundle for both releases:

$ # v0.2.0-alpha.4
URI:https://github.com/santosr2/TerraTidy/.github/workflows/release.yml@refs/tags/v0.2.0-alpha.4

$ # v0.2.0
URI:https://github.com/santosr2/TerraTidy/.github/workflows/release.yml@refs/heads/main

Expected Behavior

Artifacts for tag vX.Y.Z are signed as .../release.yml@refs/tags/vX.Y.Z, whichever path published them.

Actual Behavior

v0.2.0 is signed as @refs/heads/main.

Why it happened

The v0.2.0 tag-triggered run failed:

$ gh api repos/santosr2/TerraTidy/actions/runs/29880216820 -q '"\(.head_branch) \(.event) \(.conclusion)"'
v0.2.0 push failure

goreleaser failed at "Run GoReleaser" — the cosign v3 / goreleaser v2.15.0 bundle problem that #250 fixed. The release was then published from the workflow_dispatch path added in that same PR:

$ gh run list --repo santosr2/TerraTidy --workflow release.yml -L 8 \
    --json createdAt,event,headBranch,conclusion \
    -q '.[]|"\(.createdAt) \(.event) ref=\(.headBranch) -> \(.conclusion)"'
2026-07-22T01:50:14Z workflow_dispatch ref=main -> failure
2026-07-22T01:39:42Z workflow_dispatch ref=main -> failure
2026-07-22T01:14:53Z workflow_dispatch ref=main -> failure
2026-07-22T01:11:16Z workflow_dispatch ref=main -> failure
2026-07-22T00:26:00Z push ref=v0.2.0 -> failure
2026-04-04T06:09:59Z push ref=v0.2.0-alpha.4 -> success

The dispatch path does check out the tag's own commit:

ref: ${{ github.event.inputs.tag || github.ref }}

so GoReleaser built the right code. But cosign sign-blob and actions/attest-build-provenance both use the ambient GitHub OIDC token, and the ref in that token is the ref the run is on — refs/heads/main for a dispatch from a branch. actions/checkout cannot change it. So the build follows the tag and the signature follows the branch, and they silently disagree.

This also affects the provenance attestation, which records the same workflow ref.

Suggested fix

Dispatch the workflow with the tag as the ref rather than passing it as an input:

gh workflow run release.yml --ref v0.2.0

Then github.ref is refs/tags/v0.2.0 for both the push and the dispatch path, the checkout is already correct without the input, and the signing identity matches the tag. A guard on github.ref_type != 'tag' keeps a branch dispatch from publishing mis-signed artifacts again.

I've opened a PR for this.

Note on existing releases: because the OIDC identity is baked into the certificate, v0.2.0's bundle can't be corrected without re-signing that release.

Where I ran into it

santosr2/TerraTidy is packaged in aqua-registry, whose config pins the identity to the tag. The automated bump to v0.2.0 fails there:

ERR install the package env=linux/amd64 package_name=santosr2/TerraTidy package_version=v0.2.0
    cosign_opts="--certificate-identity-regexp, ^https://github\.com/santosr2/TerraTidy/\.github/workflows/.+\.ya?ml@refs/tags/\Qv0.2.0\E$, ..."
    error="verify with Cosign"

Investigated with Claude Code; every command and its output above is from a run I actually made. I reviewed the findings and own them.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinggoGo language

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions