# How actions/checkout Handles SSH Known Hosts and Strict Host Key Checking

> Discover how actions/checkout manages SSH known hosts and strict host key checking. Learn about temporary known-hosts files and custom GIT_SSH_COMMAND for secure Git operations.

- Repository: [GitHub Actions/checkout](https://github.com/actions/checkout)
- Tags: how-to-guide
- Published: 2026-07-16

---

**When you provide an SSH deploy key, actions/checkout constructs a temporary known-hosts file and exports a custom GIT_SSH_COMMAND that enforces strict host-key verification when the ssh-strict input is enabled.**

The `actions/checkout` GitHub Action manages SSH authentication securely by generating isolated configuration files rather than modifying the runner's global SSH settings. When using the `ssh-key` input, the action implements a multi-step process in [`src/git-auth-helper.ts`](https://github.com/actions/checkout/blob/main/src/git-auth-helper.ts) to handle known hosts and strict host-key checking without persisting sensitive data to the runner's default `~/.ssh` directory.

## SSH Authentication Architecture

### The Known Hosts File Construction

In [`src/git-auth-helper.ts`](https://github.com/actions/checkout/blob/main/src/git-auth-helper.ts), the `configureSsh()` function creates a temporary known-hosts file that consolidates three distinct sources:

1. The runner's existing `~/.ssh/known_hosts` file (if present)
2. Additional host entries provided via the `ssh-known-hosts` input
3. An implicit entry for `github.com` that ships with the action

The concatenated content is written to a unique path under `$RUNNER_TEMP` (e.g., `$RUNNER_TEMP/a1b2c3_known_hosts`). This path is immediately registered via `stateHelper.setSshKnownHostsPath()` to ensure the file can be located and deleted during the post-action cleanup phase.

### Building the GIT_SSH_COMMAND

The action constructs a custom SSH command string that enforces specific security policies. It locates the system SSH binary using `io.which('ssh')`, then builds the command with the following components:

- **`-i "$RUNNER_TEMP/<key-file>"`**: Points to the temporary private key file
- **`-o "UserKnownHostsFile=$RUNNER_TEMP/<known-hosts-file>"`**: Isolates host verification to the temporary file
- **Strict host-key checking**: When `ssh-strict` is `true`, the action appends `-o StrictHostKeyChecking=yes -o CheckHostIP=no` as documented in [`adrs/0153-checkout-v2.md`](https://github.com/actions/checkout/blob/main/adrs/0153-checkout-v2.md)

This complete command string is exported as the `GIT_SSH_COMMAND` environment variable, ensuring all subsequent Git operations (`git clone`, `git fetch`, submodule updates) use these exact SSH settings.

## Configuration Inputs and Workflow Usage

The [`action.yml`](https://github.com/actions/checkout/blob/main/action.yml) file defines three inputs that control SSH behavior:

- **`ssh-key`**: The private SSH key for authentication
- **`ssh-known-hosts`**: Additional known hosts entries in standard SSH format
- **`ssh-strict`**: Boolean flag to enable strict host-key checking

When `persist-credentials: true`, the action also writes the SSH command to the repository's local Git config under `core.sshCommand`. This ensures submodule operations inherit the same authentication settings as the parent repository.

Example workflow configuration:

```yaml
steps:
  - uses: actions/checkout@v4
    with:
      ssh-key: ${{ secrets.DEPLOY_SSH_KEY }}
      ssh-known-hosts: |
        my.custom.host ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC...
      ssh-strict: true

```

This generates an environment variable similar to:

```bash
GIT_SSH_COMMAND="ssh -i \"$RUNNER_TEMP/8f2c3a\" \
  -o StrictHostKeyChecking=yes -o CheckHostIP=no \
  -o \"UserKnownHostsFile=$RUNNER_TEMP/8f2c3a_known_hosts\""

```

## Cleanup and Security

The action implements secure cleanup through the `removeAuth()` function in [`src/git-auth-helper.ts`](https://github.com/actions/checkout/blob/main/src/git-auth-helper.ts), which invokes `removeSsh()` to delete both the temporary private key and known-hosts files from `$RUNNER_TEMP`. It also clears the `core.sshCommand` Git configuration to prevent credential leakage to subsequent workflow steps.

The combination of `StrictHostKeyChecking=yes` with `CheckHostIP=no` ensures that host keys are verified against the provided known-hosts file while avoiding IP-based verification that could fail in dynamic cloud environments.

## Summary

- **Temporary known-hosts file**: Concatenates system, user-provided, and built-in GitHub entries into an isolated file under `$RUNNER_TEMP`.
- **Strict host-key checking**: Enabled via `ssh-strict: true`, adding `-o StrictHostKeyChecking=yes` to the SSH command as implemented in [`src/git-auth-helper.ts`](https://github.com/actions/checkout/blob/main/src/git-auth-helper.ts).
- **GIT_SSH_COMMAND**: Exported environment variable ensures all Git operations use the custom key and verification settings.
- **Automatic cleanup**: Temporary files and Git configurations are removed via `stateHelper` when the action completes.

## Frequently Asked Questions

### Does actions/checkout verify GitHub's host key by default?

Yes. The action includes a built-in known-hosts entry for `github.com` that is automatically appended to the temporary known-hosts file, ensuring verification occurs even if the runner's global `~/.ssh/known_hosts` does not contain GitHub's key.

### What happens when ssh-strict is set to false?

When `ssh-strict` is disabled, the action omits the `-o StrictHostKeyChecking=yes` flag from the SSH command. This allows connections to proceed without strict verification, though the `UserKnownHostsFile` option still points to the temporary file containing any explicitly provided host keys.

### How does the action handle SSH keys for submodules?

When `persist-credentials: true`, the action writes the SSH command to the repository's Git config under `core.sshCommand`. This configuration persists for submodule operations, ensuring they use the same SSH key and known-hosts settings as the parent repository.

### Where are the temporary SSH files stored?

The action stores temporary files in the directory specified by `$RUNNER_TEMP`, generating unique filenames for both the private key and known-hosts file. These paths are tracked via `stateHelper.setSshKnownHostsPath()` and `stateHelper.setSshKeyPath()` to ensure reliable cleanup during the post-action phase.