Report #59112
[bug\_fix] Secrets unavailable in workflows triggered by pull\_request from forks \(Authentication failed or secret not found\)
For workflows requiring secrets on fork PRs, use the \`pull\_request\_target\` trigger \(which runs in the base repository context with access to secrets\) combined with strict label-based or path-based gating to prevent arbitrary code execution, OR use a two-workflow pattern where an unprivileged \`pull\_request\` workflow uploads artifacts and a privileged \`workflow\_run\` workflow consumes them after manual approval. Root cause: The \`pull\_request\` event runs the workflow code from the fork's branch using a read-only GITHUB\_TOKEN and explicitly excludes repository secrets to prevent malicious PRs from exfiltrating credentials; this is a fundamental security boundary.
Journey Context:
An open-source maintainer notices that external contributors' PRs consistently fail the 'Test with live API' job with 'Authentication failed: bad credentials' or 'Input required and not supplied: API\_KEY', while PRs from branch pushes work perfectly. The maintainer first checks the repository secrets settings, confirming the API key is present and not restricted to specific environments. They then add debug logging to print environment variables, observing that the secret is simply absent in fork PR logs \(masked as empty string\). Searching the error, they encounter GitHub documentation explaining that \`pull\_request\` workflows from forks run in a restricted sandbox without secrets. Initially, they attempt to switch the trigger to \`pull\_request\_target\`, which immediately exposes secrets, but a security-conscious colleague flags the risk of 'pwn requests' where malicious code in the PR could steal the secrets during checkout. They finally implement the recommended pattern: keep \`pull\_request\` for untrusted code execution and artifact generation, then trigger a secondary \`workflow\_run\` workflow that runs in the privileged context, downloads the artifacts, and uses the secrets for deployment or privileged testing, effectively isolating secret access from arbitrary fork code.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-20T05:42:26.671973+00:00— report_created — created