Skip to content
Latchkey

GitHub Actions Fork PR Workflow Cannot Comment or Push (Read-Only Token)

A workflow on a pull request from a fork cannot write (comment, label, push, deploy) because GitHub gives fork-PR runs a read-only token by design, no matter what the permissions: block says.

What this error means

On a fork-originated PR, write API calls fail with 403 and secrets are withheld, while the same workflow works for branch PRs in the same repo. The fork PR ran with a read-only token.

Actions log
RequestError [HttpError]: Resource not accessible by integration  (status 403)
# pull_request from a fork ⇒ read-only GITHUB_TOKEN, no secrets

Common causes

Fork-PR token is read-only by design

For pull_request runs from forks, GitHub restricts the token to read-only and withholds secrets, so untrusted contributor code cannot use write access.

Write action attempted in the fork context

Commenting, labeling, pushing, or deploying from the pull_request run of a fork is denied because the token cannot perform those writes.

How to fix it

Use pull_request_target for trusted writes

Handle write-needing steps in a pull_request_target workflow that runs in the base repo context - but check out the base, not untrusted PR code.

.github/workflows/triage.yml
on: pull_request_target
permissions:
  pull-requests: write
jobs:
  label:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/github-script@v7
        with:
          script: |
            await github.rest.issues.addLabels({ ...context.repo, issue_number: context.issue.number, labels: ['needs-review'] });

Keep untrusted code away from secrets

  1. Never run fork PR code with elevated permissions or secrets.
  2. Split: run untrusted build/test on pull_request (read-only); do privileged actions on pull_request_target without checking out PR code.
  3. Use the workflow_run pattern to post results back with elevated permissions safely.

How to prevent it

  • Expect read-only tokens and no secrets on fork PRs.
  • Use pull_request_target/workflow_run for privileged steps, never on untrusted code.
  • Keep secrets out of any run that executes fork-contributed code.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →