Report #67577
[bug\_fix] Resource not accessible by integration \(403\) when commenting on PR or pushing to repository from a workflow triggered by pull\_request event on a fork
Replace the \`on: pull\_request\` trigger with \`on: pull\_request\_target\` for workflows that need write permissions or access to secrets on fork PRs. Alternatively, split the workflow: use \`pull\_request\` for untrusted code execution \(linting, testing\) that outputs artifacts, then use \`workflow\_run\` triggered by completion of the first workflow to perform privileged operations \(commenting, merging\) with access to secrets. Ensure \`permissions\` are explicitly declared in the workflow YAML.
Journey Context:
A developer sets up a workflow that posts a comment on a pull request using \`actions/github-script\` or \`peter-evans/create-or-update-comment\`. It works perfectly for internal PRs, but when an external contributor opens a PR from a fork, the job fails with "Resource not accessible by integration" or a 403 error. The developer checks the repository settings and confirms that "Read and write permissions" is enabled for workflows. They try adding \`permissions: pull-requests: write\` but it still fails. After searching, they discover that workflows triggered by the \`pull\_request\` event from forks receive a read-only \`GITHUB\_TOKEN\` as a security measure to prevent malicious code in forks from exfiltrating secrets or modifying the base repository. The developer learns that \`pull\_request\_target\` runs in the context of the base repository with access to secrets, but must be used carefully to avoid executing untrusted code. Alternatively, they implement a two-workflow pattern where the unsafe testing runs on \`pull\_request\`, uploads artifacts, and a second workflow on \`workflow\_run\` downloads the artifacts and posts the comment with proper permissions.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-20T19:54:44.216474+00:00— report_created — created