# Understanding the Credential Security Model in actions/checkout v6+

> Explore the credential security model in actions/checkout v6+. Learn how temporary files and Git includeIf directives prevent credential leakage for enhanced security.

- Repository: [GitHub Actions/checkout](https://github.com/actions/checkout)
- Tags: internals
- Published: 2026-08-30

---

**Starting with version 6, actions/checkout isolates authentication tokens in temporary files under `$RUNNER_TEMP` instead of writing them to `.git/config`, leveraging Git `includeIf` directives and automatic cleanup to prevent credential leakage.**

The `actions/checkout` action is the official GitHub Action for cloning repositories into workflow runners. Beginning with version 6, the **credential security model in actions/checkout v6+** was fundamentally redesigned to eliminate direct storage of sensitive tokens in the repository's persistent Git configuration, significantly reducing the attack surface for "pwn-request" style vulnerabilities.

## Temporary Credentials File Architecture

Rather than embedding secrets directly into `.git/config`, the action creates a **temporary credentials file** inside the runner’s `$RUNNER_TEMP` directory.

### UUID-Based Path Generation

The action generates a unique path for each run to prevent collisions and predictable file locations. In [`src/git-auth-helper.ts`](https://github.com/actions/checkout/blob/main/src/git-auth-helper.ts), the `getCredentialsConfigPath()` method constructs a file named `git-credentials-<uuid>.config` (lines 16-28). This ensures that even if the runner is shared or compromised during execution, the credential file path cannot be guessed by other processes.

### Placeholder-to-Token Replacement Strategy

To avoid exposing the real token in process listings or temporary file metadata during creation, the action implements a two-phase write process. First, it writes a placeholder string `AUTHORIZATION: basic ***` to the temporary file (lines 63-65). Immediately after file creation, it replaces the placeholder with the actual Base64-encoded token in the format `x-access-token:<PAT>` (lines 44-58). This minimizes the window where sensitive material exists in cleartext on disk.

## Git includeIf Scoping and Isolation

The action registers the temporary credentials file with Git using conditional configuration directives rather than global settings.

For the primary checkout repository, [`src/git-auth-helper.ts`](https://github.com/actions/checkout/blob/main/src/git-auth-helper.ts) adds an `includeIf.gitdir:<repo-path>.path` entry that points to the temporary file (lines 70-84). Similar entries are configured for work-tree and container paths when applicable. This **scopes the token to the checkout only**, ensuring that Git uses the credentials solely for operations within the designated repository path without polluting the global Git configuration or affecting other repositories on the runner.

## Automatic Cleanup and Persistence Controls

The security model ensures credentials do not persist beyond the job lifecycle through explicit cleanup routines and user-configurable persistence settings.

### Post-Job Cleanup Mechanism

The `removeToken()` function (lines 72-78 in [`src/git-auth-helper.ts`](https://github.com/actions/checkout/blob/main/src/git-auth-helper.ts)) executes during the post-job phase to delete the temporary credentials file. This guarantees that the secret **never remains on the runner** after the step finishes, even if the runner is reused for subsequent jobs or remains idle.

### Controlling Credential Persistence

Users can control this behavior via the `persist-credentials` input, which defaults to `true`. When set to `false` (as defined in [`src/input-helper.ts`](https://github.com/actions/checkout/blob/main/src/input-helper.ts) at line 168), the action skips the `includeIf` registration step entirely. In this mode, the token is available only for the initial checkout operation and is not retained for later Git commands such as `git push` or `git fetch`.

## SSH Authentication Handling

The temporary file model extends to SSH authentication. When an SSH key is supplied, the action writes it to a temporary file under `$RUNNER_TEMP`, builds a `GIT_SSH_COMMAND` environment variable, and optionally stores `core.sshCommand` in the temporary Git configuration when `persist-credentials` is enabled (lines 50-60 in [`src/git-auth-helper.ts`](https://github.com/actions/checkout/blob/main/src/git-auth-helper.ts)). All temporary SSH material is subsequently removed via the `removeSsh()` cleanup function.

## Practical Configuration Examples

The following configurations demonstrate the credential security model in practice:

```yaml

# Standard checkout with credentials persisted for later git commands

- uses: actions/checkout@v6
  with:
    token: ${{ secrets.GITHUB_TOKEN }}
    persist-credentials: true

```

```yaml

# Checkout without persisting credentials (one-off fetch only)

- uses: actions/checkout@v6
  with:
    token: ${{ secrets.GITHUB_TOKEN }}
    persist-credentials: false

```

When `persist-credentials: false`, only the initial clone and fetch operations are authenticated. Any subsequent `git push`, `git fetch`, or submodule operations will fail unless you provide an alternative authentication method.

## Summary

- **actions/checkout v6+** stores authentication tokens in temporary files under `$RUNNER_TEMP` rather than in `.git/config`.
- The `GitAuthHelper` class generates unique credential paths and uses placeholder swapping to minimize token exposure during file creation.
- Git `includeIf` directives scope credentials to specific repository paths, preventing cross-repository access.
- The `removeToken()` and `removeSsh()` functions ensure automatic cleanup of all temporary authentication material in the post-job phase.
- The `persist-credentials` input allows workflows to opt out of credential retention entirely when only the initial checkout requires authentication.

## Frequently Asked Questions

### How does actions/checkout v6+ store credentials differently from previous versions?

Previous versions wrote tokens directly into the repository's `.git/config` file, leaving credentials on disk in the workspace. Version 6+ writes to temporary files outside the workspace and uses Git `includeIf` directives to reference them, ensuring credentials are isolated from the repository directory and automatically removed after the job.

### What happens to the temporary credential file after the job completes?

The `removeToken()` function executes automatically during the post-job cleanup phase (defined in [`src/git-auth-helper.ts`](https://github.com/actions/checkout/blob/main/src/git-auth-helper.ts)), deleting the temporary credentials file from `$RUNNER_TEMP`. This ensures the secret is not left behind on self-hosted runners or reusable workflow environments.

### Can I prevent credentials from persisting for subsequent steps?

Yes. Set `persist-credentials: false` in the action inputs. According to the source code in [`src/input-helper.ts`](https://github.com/actions/checkout/blob/main/src/input-helper.ts) (line 168), this skips the `includeIf` configuration step, meaning the token is used only for the initial checkout and is immediately unavailable for any subsequent Git operations within the same job.

### How are SSH keys handled in this security model?

SSH keys follow the same temporary file pattern. The action writes keys to a temporary location under `$RUNNER_TEMP`, configures `GIT_SSH_COMMAND` and `core.sshCommand` to use them, and invokes `removeSsh()` during cleanup to delete the material. This mirrors the HTTP credential approach, ensuring SSH private keys never persist in environment variables or configuration files beyond the job duration.