# How the actions/checkout Action Manages Authentication

> Learn how the actions/checkout action manages authentication using HTTPS tokens or SSH keys. It injects and cleans up credentials for secure Git operations.

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

---

**The `actions/checkout` action supports two authentication methods—HTTPS via token and SSH via private key—injecting credentials into Git's configuration before cloning and cleaning them up after the job completes.**

The authentication layer of `actions/checkout` is critical for securely accessing private repositories in GitHub Actions workflows. According to the source code in the `actions/checkout` repository, the action handles credential injection through a dedicated authentication helper that operates before any Git commands execute. This architecture ensures that sensitive tokens and SSH keys remain masked in logs while providing seamless access to protected resources.

## Authentication Architecture Overview

The authentication flow begins in [`src/input-helper.ts`](https://github.com/actions/checkout/blob/main/src/input-helper.ts), which parses workflow inputs like `token`, `ssh-key`, `ssh-known-hosts`, and `persist-credentials` into a `GitSourceSettings` object. These settings are passed to [`src/git-auth-helper.ts`](https://github.com/actions/checkout/blob/main/src/git-auth-helper.ts), where the `createAuthHelper(git, settings)` factory function instantiates a `GitAuthHelper` class. This helper coordinates two distinct authentication strategies: HTTPS token-based auth and SSH key-based auth.

## How HTTPS Token Authentication Works

When you provide a `token` input (defaulting to `GITHUB_TOKEN`), the action configures Git to send an authorization header with every HTTPS request.

### Token Header Generation and Masking

In [`src/git-auth-helper.ts`](https://github.com/actions/checkout/blob/main/src/git-auth-helper.ts), the `configureToken()` method constructs a basic authentication header from the supplied token. The action immediately registers the raw token as a secret using `core.setSecret()` to prevent exposure in workflow logs. To avoid leaking the credential through process audit logs, the implementation writes a placeholder string (`AUTHORIZATION: basic ***`) to a temporary credentials file, then replaces the placeholder with the actual base64-encoded token value.

### Repository Configuration Injection

The credentials are injected into Git's configuration through conditional includes. The helper writes an `includeIf.gitdir:` entry pointing to the temporary credentials file directly into the repository's local Git config. If `persist-credentials` is set to `true`, the action instead uses a global `include.path` directive, allowing subsequent Git commands in the same job to reuse the authentication without re-entering the token.

## How SSH Key Authentication Works

For repositories requiring SSH access, the action accepts an `ssh-key` input containing a base64-encoded PEM private key.

### Temporary Key Storage and Environment Setup

The `configureSsh()` method in [`src/git-auth-helper.ts`](https://github.com/actions/checkout/blob/main/src/git-auth-helper.ts) decodes the key and writes it to a temporary file within `RUNNER_TEMP`. It also constructs a combined `known_hosts` file, incorporating any user-provided hosts from the `ssh-known-hosts` input alongside default GitHub hosts. The helper then builds a custom `GIT_SSH_COMMAND` that explicitly points to the temporary private key and known-hosts file.

### Persistent SSH Configuration

When `persist-credentials` is enabled, the action stores the SSH command in the repository's Git configuration under the `core.sshCommand` key. For repositories with submodules, `configureSubmoduleAuth()` applies the same `core.sshCommand` setting to each submodule's local config, ensuring recursive clones authenticate correctly.

## Global vs. Local Credential Storage

The action distinguishes between job-scoped and repository-scoped authentication through two separate configuration paths.

**Local Repository Configuration**: By default, credentials are scoped only to the specific repository being checked out. The `configureAuth()` method sets up token or SSH authentication specifically for the target working directory.

**Global Job Configuration**: When workflows require authentication for multiple repositories or subsequent Git commands, `configureGlobalAuth()` creates a temporary HOME directory, copies the existing global `.gitconfig`, and applies authentication settings globally. This approach ensures that tools spawning separate Git processes inherit the necessary credentials without modifying the runner's permanent user configuration.

## Post-Job Credential Cleanup

Security cleanup occurs in the action's post-run phase, registered in [`src/main.ts`](https://github.com/actions/checkout/blob/main/src/main.ts). The `removeAuth()` and `removeGlobalConfig()` methods in [`src/git-auth-helper.ts`](https://github.com/actions/checkout/blob/main/src/git-auth-helper.ts) delete temporary SSH keys, remove the known-hosts files, and unset all Git configuration keys added during setup. This cleanup ensures that temporary credentials do not persist on the runner for subsequent jobs, even if the workflow fails or is cancelled.

## Practical Usage Examples

Configure HTTPS authentication with automatic cleanup:

```yaml
steps:
  - uses: actions/checkout@v4
    with:
      token: ${{ secrets.GITHUB_TOKEN }}
      persist-credentials: false

```

Configure SSH authentication with persistent credentials for subsequent Git commands:

```yaml
steps:
  - uses: actions/checkout@v4
    with:
      ssh-key: ${{ secrets.SSH_PRIVATE_KEY }}
      ssh-known-hosts: ${{ secrets.SSH_KNOWN_HOSTS }}
      persist-credentials: true
      submodules: true

```

## Summary

- **`actions/checkout`** supports **HTTPS token** and **SSH key** authentication methods, handling both through the `GitAuthHelper` class in [`src/git-auth-helper.ts`](https://github.com/actions/checkout/blob/main/src/git-auth-helper.ts).
- **Token authentication** injects an authorization header via Git's `includeIf` configuration, with values masked to prevent log exposure.
- **SSH authentication** writes temporary keys to `RUNNER_TEMP` and configures `GIT_SSH_COMMAND` for secure transport.
- The **`persist-credentials`** input controls whether authentication persists in repository config (`true`) or is removed immediately after checkout (`false`).
- **Automatic cleanup** in the post-run phase removes all temporary files and configuration entries to prevent credential leakage.

## Frequently Asked Questions

### How does actions/checkout handle the GitHub token securely?

The action registers the token as a secret using `core.setSecret()` immediately upon receipt, and writes credentials to temporary files using placeholder replacement to avoid exposing the value in process logs. According to the implementation in [`src/git-auth-helper.ts`](https://github.com/actions/checkout/blob/main/src/git-auth-helper.ts), the actual token value is never written to disk in plaintext during the initial configuration phase; instead, a placeholder is replaced atomically.

### What is the difference between persist-credentials true and false?

When `persist-credentials` is set to `true`, the action stores authentication configuration in the repository's local Git config (or global config for `configureGlobalAuth()`), allowing subsequent steps to run Git commands without re-authenticating. When set to `false` (recommended for security), the action removes all credential configurations and temporary files immediately after the checkout completes, limiting the exposure window.

### Can I use SSH authentication for submodules?

Yes. When you provide an `ssh-key` and set `submodules: true`, the `configureSubmoduleAuth()` function in [`src/git-auth-helper.ts`](https://github.com/actions/checkout/blob/main/src/git-auth-helper.ts) iterates through all submodules and sets the `core.sshCommand` configuration in each submodule's local config to use the same temporary SSH key and known-hosts file used for the parent repository.

### Where does actions/checkout store temporary SSH keys?

The action stores temporary SSH keys and known-hosts files in the directory specified by the `RUNNER_TEMP` environment variable. These files are created by the `configureSsh()` method and are automatically deleted during the post-job cleanup phase by `removeAuth()`, ensuring no private key material persists on the self-hosted or GitHub-hosted runner after the workflow completes.