Skip to content

safe-outputs.github-token: no hook to inject a same-job mint step before safe_outputs checkout or in the conclusion job (masked STS tokens unusable) #52608

Description

@stephen2002119

Summary

safe-outputs.github-token accepts a same-job ${{ steps.<id>.outputs.token }} expression (added in #47766 / #48101, to survive the masked-cross-job scrub of #25122). But there is no frontmatter hook to actually inject that mint step before every consumer in the safe_outputs and conclusion jobs. So the accepted expression compiles to a lock that fails actionlint (references an undefined step) and would be empty at runtime.

Same-job minting therefore only works for the agent job (via top-level pre-steps, #25242). For a token-minting action like octo-sts/action (masked output, no stored secret), there is no working configuration on the current compiler.

Verified identical on v0.85.4 and v0.86.2.

Repro

Minimal frontmatter (any masked token-minting action reproduces it; octo-sts shown):

permissions:
  contents: read
  id-token: write
pre-steps:
  - name: Mint token (agent job) — this half works
    id: octosts
    uses: octo-sts/action@v1.1.1
    with: { scope: ${{ github.repository }}, identity: my-policy }
safe-outputs:
  push-to-pull-request-branch:
  id-token: write
  steps:
    - name: Mint token (safe-output jobs)
      id: octosts
      uses: octo-sts/action@v1.1.1
      with: { scope: ${{ github.repository }}, identity: my-policy }
  github-token: ${{ steps.octosts.outputs.token }}

gh aw compile --actionlint produces (abridged):

lock.yml: error: [expression] property "octosts" is not defined ...   # safe_outputs "Checkout repository" token:
lock.yml: error: [expression] property "octosts" is not defined ...   # safe_outputs "Configure Git credentials" GIT_TOKEN:
lock.yml: error: [expression] property "octosts" is not defined ...   # conclusion "Process no-op messages" github-token:
lock.yml: error: [expression] property "octosts" is not defined ...   # conclusion "Log detection run" / "Record missing tool" / "Record incomplete" / "Update reaction comment"

Root cause

safe-outputs.github-token is applied to three jobs (agent, safe_outputs, conclusion), but the only step-injection hooks don't cover the consumers:

  1. safe_outputs jobsafe-outputs.steps are documented to run "after checking out the repository … and before any safe-output code executes." But the job's own Checkout repository and Configure Git credentials steps (emitted for push-to-pull-request-branch) consume the token and run before safe-outputs.steps. So the mint step lands after two of its consumers. There is no safe-outputs.pre-steps (pre-checkout) hook.

  2. conclusion job — has no step-injection hook at all, yet the compiler wires the token into its unguarded reporting handlers (Process no-op messages, Log detection run, Record missing tool, Record incomplete, Update reaction comment). These run every time the job runs (if: always() && needs.agent.result != 'skipped' …), so at runtime they'd hit actions/github-script with an empty required github-tokenError: Input required and not supplied: github-token.

This is the same failure mode as #25122, but for the two jobs that #25242 (agent-only pre-steps) did not address.

Why the existing paths don't cover it

Proposed fixes (any one closes the gap)

  1. safe-outputs.pre-steps — inject before the safe_outputs checkout/git-credential steps (mirror of top-level pre-steps for the agent job), and apply the same steps to the conclusion job. Then ${{ steps.<id>.outputs.token }} resolves in every consumer.
  2. Give the conclusion job a step-injection hook (it currently has none).
  3. Treat a same-job steps.*.outputs.token in safe-outputs.github-token as first-class the way safe-outputs.github-app is — i.e. the compiler orders the referenced mint step ahead of every consumer in each safe-output job (or errors clearly if it can't).

Environment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions