How Authentication is Configured in actions/checkout: PAT vs SSH Implementation
The actions/checkout action configures authentication by reading workflow inputs in src/input-helper.ts and applying them through src/git-auth-helper.ts, which sets up either an HTTP extra header with a base64-encoded personal access token or a temporary SSH key file with a custom GIT_SSH_COMMAND.
The actions/checkout GitHub Action supports two distinct authentication mechanisms to access private repositories: Personal Access Tokens (PAT) via HTTPS and SSH keys. Understanding how authentication is configured in actions/checkout requires examining the TypeScript source files that parse workflow inputs and translate them into Git configuration commands.
Authentication Mechanisms Overview
The action implements two primary authentication paths:
- Personal Access Token (PAT): Provided via the
tokeninput, stored inIGitSourceSettings.authToken, and applied as an HTTP extra header (http.<host>/.extraheader) containing a base64-encodedx-access-tokencredential. - SSH Key: Provided via the
ssh-keyinput (with optionalssh-known-hosts,ssh-strict, andssh-user), stored inIGitSourceSettings.sshKey, and applied through a temporary key file andGIT_SSH_COMMANDenvironment variable.
Input Parsing and Configuration
Reading Workflow Inputs
Authentication configuration begins in src/input-helper.ts within the getInputs() function. At approximately line 139, the action reads the token input, which defaults to the GitHub-provided GITHUB_TOKEN secret:
// Line ~139 - Authentication token
result.authToken = core.getInput('token', {required: true})
Immediately following at lines 142-148, the function gathers SSH-related parameters:
// Lines ~142-148 - SSH configuration
result.sshKey = core.getInput('ssh-key')
result.sshKnownHosts = core.getInput('ssh-known-hosts')
result.sshStrict = (core.getInput('ssh-strict') || 'true').toUpperCase() === 'TRUE'
result.sshUser = core.getInput('ssh-user')
These values populate the IGitSourceSettings interface, which is passed to the authentication helper when the checkout step executes.
Token-Based Authentication
HTTP Extra Header Construction
When a PAT is provided, src/git-auth-helper.ts handles the configuration through the configureToken() method. At lines 55-65, the helper constructs the Git configuration key and value:
const serverUrl = urlHelper.getServerUrl(this.settings.githubServerUrl)
this.tokenConfigKey = `http.${serverUrl.origin}/.extraheader`
const basicCredential = Buffer.from(`x-access-token:${this.settings.authToken}`, 'utf8')
.toString('base64')
this.tokenConfigValue = `AUTHORIZATION: basic ${basicCredential}`
The tokenConfigKey follows the Git credential pattern http.<host>/.extraheader, which instructs Git to include the specified header in all HTTPS requests to that host.
Temporary Credential Storage
At lines 26-44, configureToken() implements a placeholder strategy to avoid exposing the token in process listings. It writes a placeholder entry into a temporary credentials configuration file, then replaces the placeholder with the actual base64-encoded authorization header. This file is added to Git's includeIf chain, ensuring the token is available for subsequent Git operations without appearing in the repository's permanent configuration.
SSH-Based Authentication
Key File and Known Hosts Setup
If sshKey is supplied, the configureSsh() method (starting around line 50 in src/git-auth-helper.ts) performs the following operations:
- Writes the private key to a temporary file under
RUNNER_TEMPwith a UUID filename. - Optionally writes known-hosts entries to a companion file, including an implicit
github.comentry if none are specified. - Sets appropriate file permissions (600) on the key file.
GIT_SSH_COMMAND Configuration
At approximately line 250, the helper constructs and exports the GIT_SSH_COMMAND environment variable:
ssh -i "$RUNNER_TEMP/<uuid>" -o StrictHostKeyChecking=yes -o UserKnownHostsFile=$RUNNER_TEMP/<uuid>_known_hosts
This command is exported via git.setEnvironmentVariable('GIT_SSH_COMMAND', ...) at lines 50-70, ensuring all Git SSH operations use the temporary key without modifying the user's global SSH configuration.
Credential Persistence and Cleanup
Persisting Credentials
The persist-credentials input (parsed at lines 149-152 in src/input-helper.ts) controls whether authentication settings survive beyond the checkout step. When set to true (the default):
- For PAT authentication: The temporary credentials file remains available for subsequent Git commands in the same job.
- For SSH authentication: The
core.sshCommandGit configuration is set to the generated SSH command, allowing later steps to execute authenticated Git operations over SSH.
Post-Job Cleanup
The action implements automatic cleanup through its post-job step (defined in action.yml and executed via dist/index.js). The removeAuth() method (lines 33-38) and related removeGlobalConfig() functions delete temporary key files, unset the HTTP extra header, and clear any core.sshCommand entries. This ensures secrets do not persist on the runner after the workflow completes.
Practical Implementation Examples
Minimal Checkout with PAT
The most common configuration uses the default GitHub token:
- name: Checkout repository
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
This creates a temporary Git config entry at http.<host>/.extraheader containing the base64-encoded x-access-token credential, authenticating all Git HTTPS operations for the job.
SSH Key Authentication
For repositories requiring SSH deployment keys:
- name: Checkout via SSH
uses: actions/checkout@v4
with:
ssh-key: ${{ secrets.DEPLOY_SSH_KEY }}
ssh-known-hosts: |
github.com ssh-rsa AAAAB3...
persist-credentials: true
This writes the private key and known-hosts to temporary files, sets GIT_SSH_COMMAND, and configures core.sshCommand in the repository's Git config, enabling authenticated SSH operations for subsequent steps.
Disabling Credential Persistence
For least-privilege security models, prevent credential persistence:
- name: Checkout (no later Git auth)
uses: actions/checkout@v4
with:
token: ${{ secrets.PAT }}
persist-credentials: false
With this configuration, the token is only used for the initial git fetch and git checkout operations. The removeAuth() method immediately cleans up the temporary configuration, preventing later steps from unintentionally accessing the repository using the PAT.
Summary
- Authentication in
actions/checkoutis configured through two primary mechanisms: PAT via thetokeninput and SSH via thessh-keyinput. - Input parsing occurs in
src/input-helper.ts(lines 139-152), wheregetInputs()populates theIGitSourceSettingsinterface. - Token authentication creates a base64-encoded HTTP extra header (
http.<host>/.extraheader) insrc/git-auth-helper.ts(lines 26-65) using thex-access-tokenscheme. - SSH authentication generates temporary key files and sets
GIT_SSH_COMMANDinsrc/git-auth-helper.ts(lines 50-70, ~250) to isolate credentials from the global SSH agent. - Credential persistence is controlled by the
persist-credentialsinput and cleaned up automatically by the post-job step invokingremoveAuth()(lines 33-38).
Frequently Asked Questions
What is the default authentication method in actions/checkout?
By default, actions/checkout uses the Personal Access Token provided via the token input, which defaults to ${{ secrets.GITHUB_TOKEN }}. As implemented in src/input-helper.ts at line 139, this token is always read and passed to the authentication helper, making HTTPS the default transport unless overridden by specifying ssh-key.
How does actions/checkout secure the token during the workflow?
The action implements a placeholder strategy in src/git-auth-helper.ts (lines 26-44) where configureToken() writes a dummy value to a temporary config file before replacing it with the actual base64-encoded credential. Additionally, tokens are never written to the permanent Git configuration; they exist only in temporary files that are deleted by the post-job cleanup step calling removeAuth().
Can I use both token and SSH authentication simultaneously?
No, the action processes these as mutually exclusive authentication paths. According to the source code in src/git-auth-helper.ts, if sshKey is present, the action configures SSH authentication via configureSsh(), while token authentication via configureToken() is typically used for HTTPS operations. The workflow should specify one method based on the repository URL scheme.
Why should I set persist-credentials to false?
Setting persist-credentials: false (parsed at lines 149-152 in src/input-helper.ts) prevents the action from leaving authentication credentials in the Git configuration or environment variables after the checkout step completes. This follows the principle of least privilege, ensuring that subsequent steps in the same job cannot accidentally or maliciously access the repository using the stored credentials.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →