Skip to content

fix(ci): pr-issue-linkage header misstates how the reusable reads the PR body #3184

Description

@kyle-sexton

Problem

.github/workflows/pr-issue-linkage.yml's header comment says the gate is safe under pull_request_target because:

the reusable reads PR body metadata from the event payload only and runs no head code

The second half is true and is what matters. The first half is not accurate at the pinned SHA 7107b34832a7b6db5d08d3b132621c599fbe5e50 (v0.14.2), whose Load current PR body step re-fetches through the API:

gh api "repos/${GITHUB_REPOSITORY}/pulls/${PR_NUMBER}" --jq '.body // ""'

with the event payload used only as FALLBACK_BODY if that call fails. The step's own comment calls it a "Live-refetch".

There is a further wrinkle worth settling in the same pass: verification against a live run could not find GH_TOKEN/GITHUB_TOKEN in that step's rendered environment, which would make the gh api call fail silently and the payload fallback the path that actually runs. If that holds, the behaviour matches the comment while the code does not — but neither the comment nor anything else records why. Establish which it is before rewording.

Why it matters more than a stale comment

The line immediately below carries # zizmor: ignore[dangerous-triggers] metadata-only gate; rationale in the header comment. A security suppression whose stated rationale is a sentence that does not describe the code is worth correcting even when the suppression is independently sound.

It is independently sound. Verified against the reusable at the pinned SHA: no actions/checkout step anywhere, permissions: declares only pull-requests: read and actions: read, and the body reaches actions/github-script through env:/GITHUB_ENV with a random heredoc delimiter rather than being spliced into script text. The conclusion holds; the stated basis does not.

Also in the same comment block

  • "Public repo: runs on the reusable's hosted default runner." The caller pins runner: ubuntu-24.04 at the with: block. The value coincides with the reusable's default, so nothing breaks, but the stated mechanism is wrong and would not follow a change to that default.
  • The no-issue marker is described as the literal "No linked issue". The constant is /\bno (?:linked|related) issue\b/iNo related issue also passes, and it is a case-insensitive regex rather than a literal. Both scans additionally run against the body with fenced and indented code blocks blanked, inline code spans masked, and HTML-commented text discarded, so a marker inside a fence does not count.

Scope note

Found while fixing #3182, whose scope was the gate-description half of this comment (a closing keyword plus ## Related, when the pinned reusable requires four sections). That half is corrected in #3183. The items above are pre-existing and were deliberately left out of that PR rather than rewritten a fourth time — #3183 went through five verification rounds, and each rewrite of this comment block introduced a new inaccuracy.

Related

Activity

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

Metadata

Metadata

Assignees

Labels

agent-readyFully specified and briefed; eligible for autonomous pickup from the frontier.priority: mediumReal value, no hard deadline; normal backlog flow.work-class: scopedA briefed fix or small feature; blast radius bounded by the brief, tests exist.

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions