Skip to content

v0.91.0: "Clean credentials" fails closed when actions/checkout persisted credentials via includeIf (clean and verify disagree) #66152

Description

@jaroslawgajewski

Summary

Since v0.91.0 (#65423, fail-closed credential cleanup), the agent job's Clean credentials step runs clean_git_credentials.sh followed by verify_git_credentials.sh. When any actions/checkout step in the job used persist-credentials: true, the verify script always fails, and the agent never starts:

Cleaning git credentials from '/home/runner/work/<repo>/<repo>/.git/config'
Found authenticated remote URLs, cleaning...
Cleaned credentials from remote.origin.url
✓ Git credentials cleaned from '/home/runner/work/<repo>/<repo>/.git/config'
ERROR: Git credentials remain in /home/runner/work/<repo>/<repo>/.git/config; refusing agent execution
##[error]Process completed with exit code 1.

Root cause

The two scripts read different things:

  • actions/checkout v6+ (actions/checkout#2286) no longer writes the token into .git/config. It writes http.https://github.com/.extraheader into ${RUNNER_TEMP}/git-credentials-<uuid>.config and links it from .git/config with includeIf.gitdir:<workspace>/.git.path, includeIf.gitdir:<workspace>/.git/worktrees/*.path and the /github/workspace container equivalents. Submodule configs get the same entries.
  • clean_git_credentials.sh edits .git/config with git config --file <path> .... It does not follow includes, so it removes the credential.* and extraheader entries in that file, but leaves both the includeIf.*.path entries and the included credentials file untouched.
  • verify_git_credentials.sh reads with git config --file <path> --includes --list. It follows the includeIf path, sees http.https://github.com/.extraheader, and exits 1.

As a result, the cleanup can never satisfy its own verification when checkout persisted credentials.

Reproduction

  1. Any gh-aw v0.91.0 / v0.91.1 workflow whose agent job checks out with persist-credentials: true. A custom steps: checkout, or a compiled checkout changed to true, both reproduce it.
  2. Run it on a GitHub-hosted runner. The checkout pinned by the compiler is actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1.
  3. Clean credentials fails as shown above. On v0.90.3, with no verify step, the same workflow runs.

Observed in a fleet that forces persist-credentials: true as a workaround for checkout's submodule cleanup failure (fatal: No url found for submodule path ..., actions/checkout#1358 / #788 / #1867, all still open). Every agentic workflow failed at this step, 6/6 smoke workflows included.

Expected

clean_git_credentials.sh removes everything verify_git_credentials.sh checks for, including credentials reached through includeIf.

Possible fix

  • In clean_git_config, for each includeIf.*.path entry whose value matches git-credentials-[0-9a-f-]+\.config$, unset the entry. Delete the referenced file if it is under RUNNER_TEMP. This mirrors checkout's own removeIncludeIfCredentials, and also applies to .git/modules/*/config.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions