Skip to content
Latchkey

How to Hand a Secret From One Step to the Next Securely in GitHub Actions

Mask the value first, then store it in GITHUB_OUTPUT; a later step reads it via the steps context, still masked.

When a step mints a token, call ::add-mask:: on it before anything else, then write name=value to $GITHUB_OUTPUT. Downstream steps read steps.<id>.outputs.<name>, which the runner keeps masked.

Steps

  • Compute the secret in a step with an id.
  • Echo ::add-mask::<value> before using or storing it.
  • Append name=value to $GITHUB_OUTPUT.
  • Read steps.<id>.outputs.<name> in later steps via env:.

Workflow

.github/workflows/ci.yml
steps:
  - id: token
    run: |
      TOKEN=$(./mint-token.sh)
      echo "::add-mask::$TOKEN"
      echo "token=$TOKEN" >> "$GITHUB_OUTPUT"
  - run: ./call-api.sh
    env:
      API_TOKEN: ${{ steps.token.outputs.token }}

Gotchas

  • Mask before writing to $GITHUB_OUTPUT; otherwise the value can surface in debug logs.
  • Step outputs do not cross job boundaries; promote to a job outputs: entry for that (and it stays masked).

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →