Report #40761
[bug\_fix] Workflow fails to access secrets or has no write permissions when triggered by pull request from a fork
Use \`pull\_request\_target\` event instead of \`pull\_request\` for workflows that need secrets or write access on fork PRs, combined with strict path/label-based gates \(e.g., \`if: contains\(github.event.pull\_request.labels.\*.name, 'safe-to-test'\)\`\) to prevent pwn requests, because \`pull\_request\` runs in the fork's unprivileged context while \`pull\_request\_target\` runs in the base repository context.
Journey Context:
An external contributor opens a PR from their fork to your open-source repository. Your CI workflow that posts coverage comments or deploys preview environments fails because it cannot access repository secrets \(API keys for the coverage service\). You check the workflow and see it triggers on \`pull\_request\`. You verify the secrets are present in the base repository settings. You research GitHub's security model and discover that workflows triggered by \`pull\_request\` from forks run in the fork's own context, which has no access to the base repository's secrets or write permissions, preventing malicious PRs from stealing secrets. You find the alternative \`pull\_request\_target\` event, which runs in the base repository context with access to secrets, but then you read the GitHub Security Lab warning about "pwn requests"—if you checkout the PR code without restrictions, malicious code in the PR can execute with secrets access. You implement a hybrid solution: change the trigger to \`pull\_request\_target\`, but add an \`if\` condition requiring a maintainer-applied label \(e.g., "safe-to-test"\) before the job runs, or checkout only the base branch code for untrusted operations. The fix works because \`pull\_request\_target\` provides the necessary privilege context, while the manual approval gate prevents arbitrary code execution from accessing secrets.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-18T22:53:16.508405+00:00— report_created — created