Authenticate git without writing the installation token into .git/config, independent of allowed_non_write_users
replaceCheckoutCredentials in src/github/operations/git-config.ts rewrites the origin remote URL to https://x-access-token:<installation token>@github.com/<owner>/<repo>.git in every mode, unless ALLOWED_NON_WRITE_USERS is set — only then does it switch to a credential helper (added in #1132) and leave .git/config token-free. Please make the token-free path selectable on its own, independent of allowed_non_write_users.
Why. Workflows that review untrusted code (fork PR heads, external contributors' PRs) can already keep credentials away from that code: actions/checkout with persist-credentials: false keeps the job token out of .git/config, and Claude Code's sandbox.credentials.envVars deny entries hide token env vars from sandboxed Bash. The action's prepare step then writes its own installation token back into $GITHUB_WORKSPACE/.git/config. Anything the agent runs in the workspace — a pyproject.toml build backend during pip install -e ., a test module collected by pytest — can read that file, and the token carries the job's permissions for the duration of the step. Today the only way to get the credential-helper path is allowed_non_write_users, which changes who may trigger runs — a much bigger security decision than how git authenticates.
Ask. Any of:
- A boolean input (e.g.
git_credential_helper: true) selecting the helper path regardless ofallowed_non_write_users. - Make the helper the default and keep URL embedding behind an opt-in.
- Scope auth to the action's own git calls (
GIT_CONFIG_COUNT/GIT_CONFIG_KEY_n/GIT_CONFIG_VALUE_n, or-c http.extraheader=…on those child processes) and leave the on-disk config untouched.
Note the interaction from #1139: a helper reading $GH_TOKEN at auth time fails when the subprocess env is scrubbed, or when a sandbox credentials.envVars deny for GH_TOKEN is in effect; a helper reading from a 0600 file outside the workspace (RUNNER_TEMP/GITHUB_ACTION_PATH), or option 3, avoids that.
Current workaround. A sandbox.credentials.files entry (Claude Code ≥ 2.1.221):
{ "path": "<workspace>/.git/config", "mode": "mask", "extract": "x-access-token:([^@]+)@", "onExtractNoMatch": "deny" }Sandboxed commands see a sentinel and git still parses its config; if the URL shape changes the file becomes unreadable rather than exposed. This protects only sandboxed Bash and depends on the exact URL shape — an action-side option would be the proper fix.
Related, not duplicates. #1509 / #1534 are about the revoked token being left in the URL after the run (cleanup); #1510 / #1721 are about removing checkout's credential; #1236 / #1711 / #1559 are about persist-credentials: false breaking the action's own fetches. This issue is about the action's token being on disk in the workspace during the run, in the default auth path.
Context: meridianlabs-ai/agents#70 (the workaround is implemented in meridianlabs-ai/agents#72).
Source: anthropics/claude-code-action