Skip to content

[aw] Safe-outputs update-project token leaking into other outputs #45993

Description

@ivancea

Summary

When update-project (or another project safe-output) is configured with its own github-token, gh aw compile sets the entire Process Safe Outputs github-script step's with.github-token to that project token — even if safe-outputs.github-token is explicitly set to a different, least-privilege token for issue/PR handlers.

This ends up in not just possible wrong privileges, but the wrong user/bot doing the changes.

Expected

  • safe-outputs.github-token → default client for Process Safe Outputs / issue handlers
  • update-project.github-token → only for Projects v2 (update_project.cjs)

Actual

Compiler prefers the project token for the step client whenever any project op is configured:

// If project operations are configured, prefer the project token for the github-script client.
if projectToken != "" {
    configToken = projectToken
} else if data.SafeOutputs != nil && data.SafeOutputs.GitHubToken != "" {
    configToken = data.SafeOutputs.GitHubToken
}

(pkg/workflow/compiler_safe_outputs_steps.go)
Rationale in-tree is that Projects v2 cannot use GITHUB_TOKEN, but that does not require elevating the shared step client when handlers can use per-config tokens.

Minimal repro

---
on: workflow_dispatch
permissions:
  contents: read
  issues: read
safe-outputs:
  github-token: ${{ secrets.ISSUE_TOKEN }}   # least-privilege: issues:write
  add-comment:
    max: 1
  update-project:
    project: "https://github.com/orgs/example/projects/1"
    max: 1
    github-token: ${{ secrets.PROJECT_TOKEN }}  # classic PAT: project
---
# noop
gh aw compile <workflow>

Observed lock output

Process Safe Outputs step gets the project token:

- name: Process Safe Outputs
  uses: actions/github-script@…
  with:
    github-token: ${{ secrets.PROJECT_TOKEN }}   # unexpected: ignored ISSUE_TOKEN

Not:

    github-token: ${{ secrets.ISSUE_TOKEN }}

Impact

Any workflow that splits credentials (ephemeral/App token for issues + classic PAT for Projects) cannot keep the PAT off issue writes at the step-client level. Workarounds: per-handler github-token on every non-project handler (those that call createAuthenticatedGitHubClient), or omit update-project from the same safe-outputs job.

Suggested fix

Keep safe-outputs.github-token as the Process Safe Outputs step client. Pass the project token only via GH_AW_PROJECT_GITHUB_TOKEN / handler config, and have project handlers always use that dedicated client (not global.github from the elevated step token).

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions