You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The fix for #1510 walks include.path entries of the local git config, but actions/checkout
does not use include.path in the normal (non-global) code path — it writes includeIf.gitdir:
entries. So replaceCheckoutCredentials still removes nothing, and the checkout credential
(the workflow GITHUB_TOKEN) stays active for every git operation in the job, overriding the
app token the action puts into the remote URL.
Observed with anthropics/claude-code-action@v1.0.199 and actions/checkout@v7.0.1.
Evidence
Job log of a real tag-mode run (@claude on an issue comment, use_commit_signing: false):
Configuring git authentication for non-signing mode
Configuring git user...
Removing existing git authentication headers...
No existing authentication headers to remove <-- cleanup found nothing
Updating remote URL with authentication...
✓ Updated remote URL with authentication token
The agent then committed and pushed successfully — but under GITHUB_TOKEN, not under the app
token, which we could confirm from the outside: the push produced nopull_request: synchronize event, so neither CI nor our review workflow ran on the commit the agent added to
its own PR. GitHub suppresses events for actions performed with GITHUB_TOKEN, and that is only
consistent with the header winning over the credentials embedded in the remote URL.
For contrast, the same repository on actions/checkout@v5.1.0 (which still wrote the header into .git/config) logged ✓ Removed existing authentication headers, and pushes from the agent did
raise synchronize — CI and review ran on bot-pushed commits. The regression appeared for us
exactly when Dependabot bumped checkout from v5.1.0 to v7.0.1.
Why the current cleanup misses it
replaceCheckoutCredentials (src/github/operations/git-config.ts, v1.0.199) unsets http.<server>/.extraheader from the local config and then from every file listed in git config --local --get-all include.path.
actions/checkout v7.0.1 (src/git-auth-helper.ts, configureToken) only writes include.path
in the globalConfig branch. In the branch that runs for a normal checkout it writes, into the
repository-local config:
plus equivalent container-path variants. None of these are include.path, so the loop iterates
over an empty list and the header survives.
Impact
Two shapes, depending on what the workflow grants GITHUB_TOKEN:
contents: write granted — the push succeeds under GITHUB_TOKEN and silently raises no
events. Downstream workflows never run on commits the agent adds to an existing PR, while the
PR still shows the checks from the previous SHA, so it looks verified. This is the failure we
hit; it is silent, which makes it worse than a hard error.
and unset http.<server>/.extraheader from each referenced file (the same git config --file <path> --unset-all call already used). Optionally also drop the includeIf.gitdir:* keys themselves once their credential file no longer holds the header.
A regression test would need to cover the non-global branch specifically — the current one only
exercises include.path, which checkout uses solely for global config.
Workaround for others hitting this
Give actions/checkout a token that is not GITHUB_TOKEN (e.g. from actions/create-github-app-token), so whichever credential wins is still one whose actions raise
events. persist-credentials: false also avoids the conflict, but it has separate reported
issues (#1236, #1711).
Summary
The fix for #1510 walks
include.pathentries of the local git config, butactions/checkoutdoes not use
include.pathin the normal (non-global) code path — it writesincludeIf.gitdir:entries. So
replaceCheckoutCredentialsstill removes nothing, and the checkout credential(the workflow
GITHUB_TOKEN) stays active for every git operation in the job, overriding theapp token the action puts into the remote URL.
Observed with
anthropics/claude-code-action@v1.0.199andactions/checkout@v7.0.1.Evidence
Job log of a real tag-mode run (
@claudeon an issue comment,use_commit_signing: false):The agent then committed and pushed successfully — but under
GITHUB_TOKEN, not under the apptoken, which we could confirm from the outside: the push produced no
pull_request: synchronizeevent, so neither CI nor our review workflow ran on the commit the agent added toits own PR. GitHub suppresses events for actions performed with
GITHUB_TOKEN, and that is onlyconsistent with the header winning over the credentials embedded in the remote URL.
For contrast, the same repository on
actions/checkout@v5.1.0(which still wrote the header into.git/config) logged✓ Removed existing authentication headers, and pushes from the agent didraise
synchronize— CI and review ran on bot-pushed commits. The regression appeared for usexactly when Dependabot bumped checkout from v5.1.0 to v7.0.1.
Why the current cleanup misses it
replaceCheckoutCredentials(src/github/operations/git-config.ts, v1.0.199) unsetshttp.<server>/.extraheaderfrom the local config and then from every file listed ingit config --local --get-all include.path.actions/checkoutv7.0.1 (src/git-auth-helper.ts,configureToken) only writesinclude.pathin the
globalConfigbranch. In the branch that runs for a normal checkout it writes, into therepository-local config:
plus equivalent container-path variants. None of these are
include.path, so the loop iteratesover an empty list and the header survives.
Impact
Two shapes, depending on what the workflow grants
GITHUB_TOKEN:contents: writegranted — the push succeeds underGITHUB_TOKENand silently raises noevents. Downstream workflows never run on commits the agent adds to an existing PR, while the
PR still shows the checks from the previous SHA, so it looks verified. This is the failure we
hit; it is silent, which makes it worse than a hard error.
contents: writenot granted — the push fails with403 Write access to repository not granted, which appears to be what configureGitAuth function incompatible with actions/checkout@v4.3.1,v5.0.1,v6 #907 describes.Suggested fix
Collect every include target rather than just
include.path, e.g.and unset
http.<server>/.extraheaderfrom each referenced file (the samegit config --file <path> --unset-allcall already used). Optionally also drop theincludeIf.gitdir:*keys themselves once their credential file no longer holds the header.A regression test would need to cover the non-global branch specifically — the current one only
exercises
include.path, which checkout uses solely for global config.Workaround for others hitting this
Give
actions/checkouta token that is notGITHUB_TOKEN(e.g. fromactions/create-github-app-token), so whichever credential wins is still one whose actions raiseevents.
persist-credentials: falsealso avoids the conflict, but it has separate reportedissues (#1236, #1711).