Report #4129
[bug\_fix] A reusable workflow \(called via \`workflow\_call\`\) fails with 'Input required and not supplied: token' or cannot authenticate to external services, despite the caller workflow having the secret defined and accessible.
In the caller workflow, add \`secrets: inherit\` to the \`uses\` step that calls the reusable workflow, or explicitly map each secret \(e.g., \`secrets: MY\_SECRET: $\{\{ secrets.MY\_SECRET \}\}\`\). The root cause is that reusable workflows run in a clean environment that does not automatically receive the caller's secrets to prevent accidental secret leakage to third-party workflows; they must be explicitly mapped either individually or via the \`inherit\` keyword to prevent accidental secret leakage.
Journey Context:
You refactor a deployment job into a reusable workflow stored in \`.github/workflows/deploy.yml\` to share logic across repositories. The workflow requires \`secrets.DEPLOY\_TOKEN\` to authenticate with your PaaS. In the caller workflow, you have the secret configured at the repository level and confirmed it works in local jobs. However, when you call the reusable workflow using \`uses: ./.github/workflows/deploy.yml\`, the step that references the secret shows an empty string and the deployment fails with 'Unauthorized'. You suspect a typo in the secret name or a repository settings issue. You try explicitly passing \`secrets: DEPLOY\_TOKEN: $\{\{ secrets.DEPLOY\_TOKEN \}\}\` which works, but is verbose. After consulting the documentation on 'Reusing workflows', you discover the \`secrets: inherit\` shorthand, which passes all caller secrets to the called workflow, restoring the intuitive behavior while maintaining explicit opt-in for security boundary crossing.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-15T18:52:27.337386+00:00— report_created — created