From e8ae83f458c712822f8c2983ed1ef2339bd561bd Mon Sep 17 00:00:00 2001 From: Chris Burns <29541485+ChrisJBurns@users.noreply.github.com> Date: Mon, 10 Aug 2026 18:54:15 +0100 Subject: [PATCH] Scope releaser permissions and bind the tag expression MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The workflow granted contents: write to every job that did not declare its own, which was verify-release and compute-build-flags — both only check out and read. The default is now read and those two say so explicitly, so no job inherits. The jobs that write already declared their own permissions, which replace the workflow default rather than extend it, so they are untouched. The asset-cleanup step interpolated github.ref_name into a command substitution. Git ref names may contain ';', '$', backticks and '|', so the value is now bound through the step's existing env: block. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/releaser.yml | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/.github/workflows/releaser.yml b/.github/workflows/releaser.yml index 705ced0bae..ce809b2643 100644 --- a/.github/workflows/releaser.yml +++ b/.github/workflows/releaser.yml @@ -25,14 +25,19 @@ on: release: types: [published] +# Read-only by default. The jobs that need to write — release-binaries and the +# reusable workflows this calls — already declare their own permissions, which +# replace this rather than extend it, so they are unaffected. permissions: - contents: write + contents: read jobs: verify-release: name: Verify Release runs-on: ubuntu-latest + permissions: + contents: read steps: - name: Checkout uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 @@ -67,6 +72,8 @@ jobs: compute-build-flags: name: Compute Build Flags runs-on: ubuntu-slim + permissions: + contents: read outputs: commit-date: ${{ steps.ldflags.outputs.commit-date }} commit: ${{ steps.ldflags.outputs.commit }} @@ -176,11 +183,15 @@ jobs: - name: Remove existing release assets (allows re-runs) env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # Bound to the environment rather than interpolated: a git ref name + # may contain ';', '$', backticks and '|', and this is a command + # substitution. + TAG: ${{ github.ref_name }} run: | # Delete existing assets so GoReleaser can re-upload when re-running a failed job set +e - for name in $(gh release view "${{ github.ref_name }}" --json assets --jq '.assets[].name' 2>/dev/null); do - gh release delete-asset "${{ github.ref_name }}" "$name" -y 2>/dev/null || true + for name in $(gh release view "$TAG" --json assets --jq '.assets[].name' 2>/dev/null); do + gh release delete-asset "$TAG" "$name" -y 2>/dev/null || true done set -e