When using reusable workflows, avoid using secrets: inherit. This forwards every secret from the caller to the callee, increasing the risk if the callee is compromised.
Mitigation: Use explicit per-secret mapping in the secrets: block of the workflow call.
Additionally, avoid using fromJSON(secrets.X).y to access structured secrets. This bypasses GitHub's automatic log redaction because the sub-fields are treated as fresh strings.
Mitigation: Store structured secrets as individual leaf secrets (e.g., API_TOKEN instead of a JSON object CREDS) and bind them directly.
# ❌ before
jobs:
call:
uses: org/shared/.github/workflows/publish.yml@v1
secrets: inherit
# ✅ after — explicit per-secret mapping
jobs:
call:
uses: org/shared/.github/workflows/publish.yml@v1
secrets:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
# ❌ before — .token bypasses redaction once fromJSON runs
jobs:
deploy:
env:
API_TOKEN: ${{ fromJSON(secrets.CREDS).token }}
steps:
- run: echo "token=$API_TOKEN" >> deploy.log
# ✅ after — split the structured secret, store each leaf separately
jobs:
deploy:
env:
API_TOKEN: ${{ secrets.API_TOKEN }}
steps:
- run: echo "token=$API_TOKEN" >> deploy.log