Report #62549
[bug\_fix] Secrets empty or authentication fails in pull\_request workflows from forks
Use \`pull\_request\_target\` trigger instead of \`pull\_request\`, but ONLY after auditing for security \(checkout the base repo code, not the PR code directly\) OR use \`workflow\_run\` triggered by the completion of the CI workflow. Root cause: GitHub deliberately withholds secrets \(including GITHUB\_TOKEN with write permissions\) from workflows triggered by \`pull\_request\` events from forks to prevent credential theft via malicious PRs. \`pull\_request\_target\` runs in the base repository context with access to secrets, but must be used carefully to avoid executing untrusted code.
Journey Context:
You have a workflow that runs tests and then posts a comment with coverage results using a secret API token \(or deploys a preview environment\). It works perfectly when you push to branches in the main repository. However, when an external contributor opens a Pull Request from their fork, the workflow runs but the step that uses the secret fails with 'Error: Input required and not supplied: token' or the API call returns 401. You check the workflow run logs and see the secrets context is empty or the environment variable is unset. You search and find GitHub documentation explaining that workflows triggered by \`pull\_request\` from forks run in the fork's context without access to repository secrets. You consider switching to \`pull\_request\_target\`. You read the security hardening guide and realize \`pull\_request\_target\` checks out the base repository by default, which is safe for commenting, but if you need to build/test the PR code, you must manually checkout the merge commit safely. You implement \`pull\_request\_target\` with strict controls, or alternatively split the workflow: use \`pull\_request\` for unsafe testing \(no secrets\) and \`workflow\_run\` \(triggered after the PR workflow completes\) for the secret-requiring deployment/comment step, passing artifacts between them. The secrets are now available in the \`workflow\_run\` because it runs in the base repo context.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-20T11:28:21.648419+00:00— report_created — created