Skip to content

gh auth setup-git does not override the git user following an actions/checkout invocation #10905

@acoulton

Description

@acoulton

Describe the bug

Running gh auth setup-git in github actions with a custom GH_TOKEN does not have any effect if the workflow has already run an actions/checkout@v4 step with default options.

Affected version

Please run gh version and paste the output below.

Steps to reproduce the behavior

  1. Create a read-only personal access token as a repository secret MY_CUSTOM_TOKEN (in a normal case this would allow write, but read-only makes it easier to see which user is attempting to push from the permissions failure error).
  2. Create a Github Actions workflow including a job with the following permissions and steps:
on:
  push:

jobs:
  update:
    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@v4
    
      - run: git commit --allow-empty -m "Test commit"
    
      - env:
          GH_TOKEN: ${{ secrets.MY_CUSTOM_TOKEN }}
        run: |
          gh auth setup-git
          git push origin
  1. Trigger the workflow and observe the output of git push

Expected vs actual behavior

I would expect the git push to be attempted with the credentials provided through GH_TOKEN to gh auth setup-git.

Therefore if secrets.MY_CUSTOM_TOKEN is a read-only token, git push should fail with output like remote: Permission to {repo} denied to {my user that owns the token}.

However, the git push is attempted with the default GITHUB_TOKEN that was used by actions/checkout. In this case because we have only granted contents:read the push fails with output like remote: Permission to {repo} denied to github-actions[bot]

Logs

remote: Permission to {REPO}.git denied to github-actions[bot].
fatal: unable to access 'https://github.com/{REPO}/': The requested URL returned error: 403

Cause

Rather than use a credential helper, actions/checkout adds a local git configuration to set an AUTHORIZATION header on http calls, like so:

# output of git config --list after actions/checkout runs.
http.https://github.com/.extraheader=AUTHORIZATION: basic ***

By default, this config is left in the .git/config file after the checkout completes. It appears that this config takes precedence over the use of gh as a credential helper, so all git operations are performed using the credentials originally set by the actions/checkout run.

It is possible to configure actions/checkout with the persist-credentials: 'false' argument, which causes it to remove this custom header before the next step runs. However, this is not immediately obvious.

Potential solutions

I think either this should be resolved by:

  • Updating the documentation for gh auth setup-git to highlight this potential issue in a github actions context and point users to the persist-credentials: 'false' option to actions/checkout.
  • Updating gh auth setup-git to fail if the git config already contains a http.{host}.extraheader=AUTHORIZATION setting for the host(s) it is attempting to configure a credential helper for, on the basis that this will not actually configure git operations as expected.

Or, by updating gh auth setup-git to remove any custom authorization header configuration when it adds the credential helpers. This could obviously have side-effects and unintended consequences so I think probably failing and alerting the user to the issue is a better solution.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingneeds-triageneeds to be reviewed

    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