head_ref is attacker-controlled on fork PRs: a fork branch named
"main" produced the same concurrency group as trusted push and
workflow_dispatch runs on this repo's main, and with
cancel-in-progress: true a fork PR could cancel trusted CI runs.
The PR number is assigned by the repo, so fork authors cannot steer a
PR run into a branch group. Push and dispatch runs keep sharing a group
per ref_name so a dispatched run is still superseded by a push.
Flagged by roborev review on PR #15.
Generated with Claude Code (claude-fable-5[1m])
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Summary
workflow_dispatchruns were grouped bygithub.ref(refs/heads/<branch>) whilepull_requestruns were grouped byhead_ref(bare branch name), so a dispatched CI run on a branch was never cancelled when a push to the same branch superseded it, and vice versagithub.ref_nameso all trigger events on the same branch share one concurrency group; PR runs andmainpush runs remain separate groups🤖 Generated with Claude Code