Report #38641
[bug\_fix] Secrets unavailable in workflows triggered by fork pull requests
Use \`pull\_request\_target\` event instead of \`pull\_request\` for workflows that require secret access for fork-based contributions, while carefully checking out the base repository code \(not the PR code\) or using a two-workflow split to prevent code execution with secret access. The root cause is that GitHub withholds secrets from \`pull\_request\` workflows on forks to prevent malicious PRs from exfiltrating credentials.
Journey Context:
You have a workflow that runs end-to-end tests requiring AWS credentials stored in repository secrets \(\`AWS\_ACCESS\_KEY\_ID\`, \`AWS\_SECRET\_ACCESS\_KEY\`\). The workflow triggers on \`pull\_request\`. When internal team members open PRs from branches within the repository, the secrets populate correctly and tests pass. However, when an external contributor forks the repository and submits a PR, the workflow runs but the AWS environment variables are empty, causing the tests to fail with 'unable to locate credentials'. You check the workflow logs and see the secrets are being accessed as \`secrets.AWS\_ACCESS\_KEY\_ID\` but resolve to empty strings. You search the documentation and find the security note explaining that secrets are not passed to workflows triggered by pull requests from forks. This is a deliberate security measure to prevent attackers from creating PRs that print or exfiltrate secrets. The solution is to use the \`pull\_request\_target\` event, which runs the workflow in the context of the base repository \(where secrets are available\) rather than the merge commit. However, you must be careful: if you checkout the PR code \(\`refs/pull/.../merge\`\) with \`pull\_request\_target\`, malicious code could access the secrets. The safe pattern is to either checkout the base branch code for linting/security scanning, or use a split workflow where the untrusted \`pull\_request\` workflow uploads artifacts, and a trusted \`workflow\_run\` \(triggered by completion\) downloads them and runs the secret-requiring tests with the secrets.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-18T19:20:11.904842+00:00— report_created — created