Reusable Workflow Secrets Inheritance
Description
When one workflow calls a reusable workflow, it can forward credentials with secrets: inherit. This passes all of the caller’s secrets to the called workflow with no per-secret control. 1 The called workflow — which may live in another repository, be maintained by a different team, or be updated independently — then has access to the caller’s complete secret store, widening the blast radius of any vulnerability or compromise in that downstream workflow. Explicitly naming the secrets a reusable workflow requires keeps each credential scoped to where it is genuinely needed. This complements Excessive Secret Exposure, which concerns bulk serialization within a single workflow.
Vulnerable Instance
- A job calls a reusable workflow via
uses:and forwards credentials withsecrets: inherit. - The reusable workflow receives every secret available to the caller, not just the ones it needs.
name: Release
on: [push]
jobs:
publish:
uses: ./.github/workflows/publish.yml
secrets: inherit # forwards ALL caller secrets downstreamMitigation Strategies
Pass only the required secrets, explicitly by name Declare each secret the reusable workflow needs and forward just those.
jobs: publish: uses: ./.github/workflows/publish.yml secrets: REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}Declare inputs in the reusable workflow Have the reusable workflow define a
workflow_callblock with explicitsecrets:entries so callers cannot accidentally over-share.Audit cross-repository reuse Be especially careful when the reusable workflow lives in a different repository or is maintained by another team;
inheritexposes your secrets to code you do not directly control.Prefer short-lived credentials Where possible, have the reusable workflow obtain its own short-lived tokens via OIDC instead of receiving long-lived secrets from the caller.
Secure Version
name: Release
on: [push]
jobs:
publish:
uses: ./.github/workflows/publish.yml
- secrets: inherit
+ secrets:
+ REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
Impact
| Dimension | Severity | Notes |
|---|---|---|
| Likelihood | secrets: inherit is convenient and widely used, often without considering how many secrets it forwards. | |
| Risk | A vulnerability or compromise in the called workflow gains access to every secret the caller holds. | |
| Blast radius | All caller secrets become reachable by the downstream workflow, which may be externally maintained. |
References
- GitHub Docs, “Reusing workflows — Passing inherited secrets to a reusable workflow,” https://docs.github.com/en/actions/using-workflows/reusing-workflows#passing-inherited-secrets-to-a-reusable-workflow 1
- GitHub Docs, “Security hardening for GitHub Actions,” https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions 2
GitHub Docs, “Reusing workflows,” https://docs.github.com/en/actions/using-workflows/reusing-workflows#passing-inherited-secrets-to-a-reusable-workflow ↩︎ ↩︎
GitHub Docs, “Security hardening for GitHub Actions,” https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions ↩︎