Scope releaser permissions and bind the tag expression - #6263
Merged
Conversation
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) <noreply@anthropic.com>
10 tasks
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #6263 +/- ##
==========================================
+ Coverage 72.70% 72.72% +0.01%
==========================================
Files 742 742
Lines 77299 77299
==========================================
+ Hits 56202 56217 +15
+ Misses 17133 17118 -15
Partials 3964 3964 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
jerm-dro
approved these changes
Aug 10, 2026
This was referenced Aug 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
First of the release-workflow changes tracked in #6253. Deliberately the smallest and most contained one, because nothing here can be exercised by a pull request —
releaser.ymlruns only onrelease: published.Summary
contents: writeto jobs that only read. It was declared at workflow level, so every job that did not declare its own inherited it —verify-releaseandcompute-build-flags, both of which just check out and read git locally. The default is nowcontents: readand those two declare it explicitly, so nothing inherits.gh release view "${{ github.ref_name }}"inside$( ). Git ref names may contain;,$, backticks and|— unlike, say, a repository name — so this one is a real sink rather than a stylistic nit. It is still gated behind repo write access, since creating a release requires it.Why the permission change is safe
A job-level
permissions:block replaces the workflow default rather than extending it, so the jobs that write were never relying on the workflow-level grant:verify-releasecontents: readcompute-build-flagscontents: readrelease-binariescontents: write,id-token: writeimage-build-and-pushskills-build-and-pushpublish-helmnotify-release-failure{}Every job in the file now states its own permissions, so this cannot drift back by someone adding a job that quietly inherits write.
Effect
releaser.ymlgoes from 4 High findings to 1; repo-wide High goes 10 → 7. The remaining one isgithub-app— the Homebrew tap token inheriting blanket installation permissions — which is deliberately left for a later change, because scoping app tokens is the part most likely to break a release and wants the App's actual installation permissions checked first.Part of #6253
Type of change
Test plan
Unit tests (
task test)E2E tests (
task test-e2e)Linting (
task lint-fix)Manual testing (describe below)
Enumerated every job in the file and confirmed which inherited the workflow-level permission, rather than assuming — only the two read-only jobs did.
Asserted programmatically that no job inherits any more.
Workflow parses as YAML;
actionlintreports nothing new.zizmoron this file:excessive-permissions1 → 0 andtemplate-injection2 → 0.This cannot be verified before merge.
releaser.ymlruns only onrelease: published, so the first real exercise is the next release. That is why this change is limited to a permissions default and a quoting fix, and why the app-token work is not in it.Does this introduce a user-facing change?
No.
Special notes for reviewers
--json assetscleanup step is a re-run convenience; if the quoting change were wrong it would fail that step rather than corrupt a release, which is part of why it was chosen to go first.needs.extract-release-actor.outputs.triggered_by, but noextract-release-actorjob exists in this workflow. The expression resolves to null and falls through to|| github.actor, so the failure-notification "Triggered by" line silently never shows the preserved release triggerer thatcreate-release-tag.ymlgoes to the trouble of extracting. Worth its own issue; changing it here would mean altering release behaviour in a pull request that cannot test it.Generated with Claude Code