From 820e5c970b5a2345be720bb36742616baea6abca Mon Sep 17 00:00:00 2001 From: jmeridth Date: Wed, 8 Jul 2026 13:07:15 -0500 Subject: [PATCH] fix(ci): run PR automation via pull_request_target for fork PRs The auto-author-assign and mark-ready-when-ready workflows trigger on pull_request, so PRs from forks get a read-only GITHUB_TOKEN and both jobs fail (assignees API denied; contents: write denied). Switch both to pull_request_target, which runs in the base-repo context with a read-write token even for fork PRs. This is safe because neither workflow checks out or executes PR-head code. Both actions operate purely on the event payload (PR number, draft flag, labels, head SHA) via the API, so the base-repo context evaluates no untrusted code. ## What/Why Auto-assign and auto-mark-ready silently fail on every external fork PR because pull_request gives forks a read-only token; pull_request_target restores a read-write token without executing fork code. ## Proof it works actionlint and pre-commit pass. Verified kenyonj/mark-ready-when-ready reads github.event.pull_request.head.sha (not github.sha) and toshimaru/auto-author-assign acts via the assignees API, so neither depends on a PR-head checkout. ## Risk + AI role Low. CI-only. Edits drafted with Claude Opus 4.8, reviewed by a human. The main review concern is confirming neither workflow ever adds a PR-code checkout in future edits, which would turn pull_request_target into a pwn-request vector. ## Review focus Whether pull_request_target is acceptable here versus gating the jobs to skip on fork PRs (which would drop the feature for external contributors instead). Signed-off-by: jmeridth --- .github/workflows/auto-author-assign.yaml | 6 +++++- .github/workflows/mark-ready-when-ready.yml | 8 +++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/workflows/auto-author-assign.yaml b/.github/workflows/auto-author-assign.yaml index f418245..30c79b8 100644 --- a/.github/workflows/auto-author-assign.yaml +++ b/.github/workflows/auto-author-assign.yaml @@ -1,7 +1,11 @@ --- name: "Auto Author Assign" +# Uses pull_request_target so the assign step gets a read-write token on fork +# PRs (pull_request hands forks a read-only token, which makes the assignees +# API call fail). Safe here: the workflow never checks out or executes PR-head +# code, it only assigns the author via the API from the event payload. on: - pull_request: + pull_request_target: types: [opened, reopened, synchronize] permissions: contents: read diff --git a/.github/workflows/mark-ready-when-ready.yml b/.github/workflows/mark-ready-when-ready.yml index fde2354..2825bfe 100644 --- a/.github/workflows/mark-ready-when-ready.yml +++ b/.github/workflows/mark-ready-when-ready.yml @@ -1,7 +1,13 @@ name: Mark PR Ready When Ready +# Uses pull_request_target so the mark-ready step gets a read-write token on +# fork PRs (pull_request hands forks a read-only token, so contents: write is +# denied and the job fails). Safe here: the workflow never checks out or +# executes PR-head code. The action reads the PR number, draft flag, labels, +# and head SHA from the event payload and acts only via the API, so running in +# the base-repo context does not evaluate any untrusted code. on: - pull_request: + pull_request_target: types: [opened, edited, labeled, unlabeled, synchronize] permissions: