Repository navigation
gh auth setup-git does not override the git user following an actions/checkout invocation #10905
Description
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
- 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).
- 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
- 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-gitto highlight this potential issue in a github actions context and point users to thepersist-credentials: 'false'option toactions/checkout. - Updating
gh auth setup-gitto fail if the git config already contains ahttp.{host}.extraheader=AUTHORIZATIONsetting 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.
Activity
ci: Fix git permissions for pushing cucumber updates
tyler-abovedesign commentedon Jan 16, 2026
Has this been fixed? I run into this pretty often