Report #8694
[bug\_fix] Secrets are empty or unavailable in workflows triggered by pull requests from forks, causing authentication failures in CI
Do not rely on secrets in \`pull\_request\` workflows for external contributions. Instead, use the \`workflow\_run\` event pattern: have the \`pull\_request\` workflow build and upload untrusted artifacts, then trigger a privileged \`workflow\_run\` workflow that downloads the artifacts and accesses secrets. Alternatively, use \`workflow\_dispatch\` for manual approval, or carefully use \`pull\_request\_target\` only with strict checkout of the base repository code, not the PR code.
Journey Context:
A development team sets up a CI pipeline that runs integration tests requiring API keys for a staging environment \(e.g., AWS credentials, SauceLabs tokens, or private registry auth\). They store these as encrypted secrets in the repository settings. When team members push branches directly to the repository, the \`pull\_request\` event triggers the workflow and secrets are injected correctly; tests pass. Then an external contributor forks the repository and submits a PR. The workflow triggers but immediately fails with "Unable to locate credentials" or "401 Unauthorized" errors. The developer examines the workflow logs and notices that the secret environment variables are empty strings or masked as \`\*\*\*\` but actually undefined. They consult GitHub documentation and learn that secrets are intentionally not passed to workflows triggered by \`pull\_request\` events from forks as a security measure against malicious PRs exfiltrating secrets. The developer initially considers switching to \`pull\_request\_target\`, which receives secrets, but reads security advisories warning that checking out the PR code with \`pull\_request\_target\` is dangerous \(pwn requests\). The established pattern they implement is a split workflow: Workflow A triggered by \`pull\_request\` builds the code and uploads artifacts \(untrusted\), with no secrets. Workflow B triggered by \`workflow\_run\` \(which runs in the context of the base repository with secrets\) downloads the artifacts and runs deployment/tests with secrets. This safely isolates untrusted code from secrets while allowing CI to function for forks.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T06:13:21.405398+00:00— report_created — created