Report #8871
[bug\_fix] Secret not found or empty in pull\_request workflows from forks
Do not use \`pull\_request\` event for workflows requiring secrets on external forks. Use the \`workflow\_run\` event pattern: an initial 'Build' workflow \(triggered by \`pull\_request\`, no secrets\) uploads artifacts; a second 'Deploy/Report' workflow triggers \`on: workflow\_run: workflows: \['Build'\] types: \[completed\]\` with \`if: $\{\{ github.event.workflow\_run.conclusion == 'success' \}\}\`, running in the base repo context with full secrets.
Journey Context:
An external contributor opened a PR from a fork. The CI workflow failed immediately on the 'Login to Docker Hub' step with 'Error: Username and password required', despite \`secrets.DOCKER\_PASSWORD\` being defined in the repository settings. Debugging revealed that \`secrets.\*\` values were empty strings in this run. Investigation of the event type showed \`pull\_request\`. Reviewing GitHub's security documentation clarified that for \`pull\_request\` events triggered by forks, secrets are intentionally withheld to prevent 'pwn requests' where malicious code in the PR could exfiltrate credentials. The initial thought was to switch to \`pull\_request\_target\`, which runs in the base repo context with secrets, but this is dangerous as it checks out untrusted code with privileged credentials. The established secure pattern involves splitting the workflow: the untrusted build runs via \`pull\_request\` without secrets, producing artifacts; a privileged workflow triggers \`on: workflow\_run\` upon completion, downloads the artifacts, and uses secrets to deploy or comment. Implementing this pattern resolved the secret availability issue while maintaining security boundaries.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T06:42:15.336043+00:00— report_created — created