Skip to content

Bug: github_mcp_app_token activation output silently skipped — regression introduced in #24251 #24569

@straub

Description

@straub

Summary

After #24251, the GitHub App token for the MCP server is minted in the activation job and passed to agent (and other jobs) via a job output. In practice the token never arrives — GitHub Actions runner silently drops the output with:

Warning: Skip output 'github_mcp_app_token' since it may contain secret.

GITHUB_MCP_SERVER_TOKEN is empty in the agent job; the GitHub MCP server runs unauthenticated.

Root Cause

actions/create-github-app-token unconditionally calls ::add-mask:: on the token it produces. Once a value is masked, the GitHub Actions runner refuses to propagate it as a job output — it emits the warning above and substitutes an empty string. This is intentional runner hardening (introduced around runner v2.308) to prevent secrets leaking across job boundaries via outputs.

The compiled activation job:

- name: Generate GitHub App token
  id: github-mcp-app-token
  uses: actions/create-github-app-token@... # v3
  with:
    app-id: ${{ vars.APP_ID }}
    private-key: ${{ secrets.APP_PRIVATE_KEY }}
    ...

outputs:
  github_mcp_app_token: ${{ steps.github-mcp-app-token.outputs.token }}
  #                      ^^^ masked → runner skips this output entirely

The security intent of #24251 is sound — app-id/private-key should not reach the agent job. But the chosen mechanism (job output) is incompatible with how actions/create-github-app-token works.

Reproduction

  1. Configure any workflow with tools.github.github-app: and compile with v0.66.1.
  2. Trigger the workflow.
  3. In the activation job's "Complete job" step, observe:

    Warning: Skip output 'github_mcp_app_token' since it may contain secret.

  4. GITHUB_MCP_SERVER_TOKEN is empty in the agent job.

Suggested Fix

The runner blocks masked values from crossing job boundaries via outputs:, but the fix options include:

  • Duplicate the minting step into each consuming job (agent, etc.), scoped so private-key is excluded from the AWF sandbox environment — the --exclude-env GITHUB_MCP_SERVER_TOKEN flag is already present on the awf invocation, so the key itself never enters the sandbox.
  • Use a custom minting script that does not call ::add-mask::, allowing the output to propagate (trades away log masking).
  • Pass via artifact rather than job output (more complex, probably not worth it).

The cleanest approach is likely reverting the activation-job output pattern for github_mcp_app_token and instead generating the token directly inside each job that needs it.

References

Metadata

Metadata

Labels

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