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-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.
Describe the bug
Running
gh auth setup-gitin github actions with a customGH_TOKENdoes not have any effect if the workflow has already run anactions/checkout@v4step with default options.Affected version
Please run
gh versionand paste the output below.Steps to reproduce the behavior
Expected vs actual behavior
I would expect the
git pushto be attempted with the credentials provided throughGH_TOKENtogh auth setup-git.Therefore if
secrets.MY_CUSTOM_TOKENis a read-only token,git pushshould fail with output likeremote: Permission to {repo} denied to {my user that owns the token}.However, the
git pushis attempted with the defaultGITHUB_TOKENthat was used by actions/checkout. In this case because we have only grantedcontents:readthe push fails with output likeremote: Permission to {repo} denied to github-actions[bot]Logs
Cause
Rather than use a credential helper,
actions/checkoutadds a local git configuration to set an AUTHORIZATION header on http calls, like so: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
ghas a credential helper, so all git operations are performed using the credentials originally set by theactions/checkoutrun.It is possible to configure
actions/checkoutwith thepersist-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:
gh auth setup-gitto highlight this potential issue in a github actions context and point users to thepersist-credentials: 'false'option toactions/checkout.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-gitto 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.