Merged
Conversation
The workflow failed on fork PRs because `pull_request` events restrict the GITHUB_TOKEN to read-only, preventing the bot from posting PR comments. Switch to `pull_request_target` so the token retains the declared `pull-requests: write` permission. Also allow maintainers to trigger preview deployments for fork PRs by checking `github.actor` (the re-run initiator) in addition to the PR author. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
miparnisari
approved these changes
Mar 30, 2026
With pull_request_target, github.head_ref is controlled by the fork author. Passing it through an environment variable instead of inline expression syntax prevents shell injection via crafted branch names. Resolves code scanning alert #8. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
miparnisari
approved these changes
Mar 30, 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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
Summary
Problem
When an external contributor opens a PR from a fork, the workflow fails at the "Post no-permission comment" step with:
This happens because the
pull_requestevent restricts theGITHUB_TOKENto read-only permissions for fork PRs, regardless of what permissions are declared in the workflow. The bot can't even post the "deployment skipped" comment.Additionally, the "re-run this workflow" link in that comment doesn't actually help — re-running produces the same result because the permission check only looks at the PR author, who still lacks write access.
Failing run: https://github.com/authzed/docs/actions/runs/23755123905/job/69223406040?pr=529
Expected workflow after this fix
Fork PR from external contributor:
github.actoris now the maintainer. The permission check sees the maintainer has write access and allows the deploymentPR from a collaborator with write access:
No change — works exactly as before.
Technical details
Four changes to
.github/workflows/vercel-preview.yml:pull_request→pull_request_target: Runs the workflow in the base repo's context so theGITHUB_TOKENgets the declaredpull-requests: writepermission, even for fork PRs. This is the core fix for the 403.Reordered steps — permission check before checkout: The permission check and comment-finding steps now run before
actions/checkout. This is important for security withpull_request_target: untrusted fork code is never checked out unless the permission gate passes. The checkout step is now conditional onsteps.permission.outputs.result == 'true'and explicitly referencesgithub.event.pull_request.head.sha(sincepull_request_targetdefaults to checking out the base branch).Permission check also inspects
github.actor: On a re-run,github.actorchanges to the person who triggered the re-run. The updated check allows deployment if either the PR author has write access OR the triggering actor (distinct from the author) has write access. This makes the "re-run this workflow" link in the no-permission comment functional.Fix code injection via
github.head_ref(resolves code scanning alert Nov dependabot updates #8): Withpull_request_target,github.head_refis attacker-controlled. It was previously interpolated directly into arun:shell step via${{ github.head_ref }}, allowing arbitrary command execution through crafted branch names. Fixed by passing it through an environment variable (HEAD_REF) and referencing it as$HEAD_REFin the shell.🤖 Generated with Claude Code