Skip to content

checkout.token from custom jobs: fails at runtime when token-minting action masks output #25122

@salekseev

Description

@salekseev

Summary

checkout.token accepts ${{ needs.<job>.outputs.token }} at compile time (fixed in #24135), but fails at runtime when the upstream token-minting action calls ::add-mask:: on its output — the same class of bug fixed for checkout.github-app in #24897 / #24902.

Any action that masks its token output (e.g., octo-sts, actions/create-github-app-token) will hit this when the token crosses a job boundary via needs.*.outputs.*.

Reproduction

Minimal .md workflow:

---
name: Cross-repo checkout via custom auth job

on:
  workflow_dispatch:

permissions:
  contents: read
  id-token: write

engine:
  id: claude
  version: "2.1.92"
  model: claude-sonnet-4-6

jobs:
  auth:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
    outputs:
      token: ${{ steps.mint.outputs.token }}
    steps:
      - name: Mint short-lived token
        uses: some-org/token-minting-action@v1
        id: mint
        with:
          scope: target-org/target-repo

checkout:
  - repository: target-org/target-repo
    path: .
    token: ${{ needs.auth.outputs.token }}
    current: true
  - path: source

safe-outputs:
  noop:
---

Read a file from the checked-out repo and call noop.

Compile

$ gh aw compile --no-check-update cross-repo-test
✓ .github/workflows/cross-repo-test.md
⚠ Compiled 1 workflow(s): 0 error(s), 1 warning(s)

Compiles successfully (schema fix from #24135 works).

Runtime failure

The agent job fails at the checkout step:

##[error]Input required and not supplied: token

The token-minting action calls ::add-mask:: before writing to GITHUB_OUTPUT. GitHub Actions runner v2.308+ then suppresses the masked value in needs.auth.outputs.token, so the checkout step receives an empty string.

Why checkout.github-app is not affected

PR #24902 moved create-github-app-token minting into the agent job at compile time — the token never crosses a job boundary. But for checkout.token referencing a custom jobs: output, the compiler passes the expression through verbatim, so the token still traverses the job boundary and gets dropped.

Relationship to prior issues

Issue What it fixed This gap
#24135 Compile-time schema rejected needs.*.outputs.* expressions ✅ Fixed — compiles now
#24897 / #24902 checkout.github-app token dropped by runner masking ✅ Fixed — minted in agent job
This issue checkout.token from custom jobs: still dropped by runner masking ❌ Not addressed

Possible solutions

  1. checkout.action — allow specifying a custom action to run in the agent job for token acquisition, analogous to how checkout.github-app inlines create-github-app-token:

    checkout:
      - repository: target-org/target-repo
        path: .
        current: true
        action:
          uses: some-org/token-minting-action@v1
          with:
            scope: target-org/target-repo
  2. Pre-checkout steps: — a frontmatter field for steps that run inside the agent job before checkout, so users can mint tokens and reference them in checkout.token via step outputs.

  3. checkout.oidc — first-class OIDC/STS support in the checkout config, where gh-aw handles the token exchange internally.

Environment

  • gh-aw: v0.67.1 (also tested compile on v0.67.0)
  • Runner: GitHub-hosted, runner v2.308+
  • Token action: octo-sts-action (masks output)

Metadata

Metadata

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions