Understanding the `persist-credentials` Input in actions/checkout: Security and Functionality Explained
The persist-credentials input controls whether authentication tokens remain in the Git configuration after actions/checkout completes, enabling subsequent authenticated Git operations when set to true while minimizing security exposure when set to false.
The actions/checkout step is essential for cloning repositories in GitHub Actions workflows. The persist-credentials input determines whether the authentication token used for the initial clone remains available for later steps, directly impacting both workflow functionality and security posture according to the actions/checkout source code.
How persist-credentials Controls Credential Lifecycle
The input accepts a boolean value that dictates the retention strategy for HTTPS tokens or SSH credentials provided to the action.
Enabling Credential Persistence (persist-credentials: true)
When set to true, the authentication token is written to the local Git configuration file (.git/config) and stored in a temporary file under $RUNNER_TEMP. This configuration allows any subsequent Git commands—such as pushing tags, pulling submodules, or making commits—to authenticate automatically without requiring additional tokens.
According to src/input-helper.ts (lines 166-168), this setting is parsed and assigned to result.persistCredentials within the IGitSourceSettings object. The credentials persist until the job completes, at which point the post-job cleanup removes them from the environment.
Disabling Credential Persistence (persist-credentials: false)
By default, persist-credentials is set to false. In this mode, the authentication token is used only for the initial repository checkout and optional submodule fetch. Immediately after these operations complete, the cleanup logic in src/git-source-provider.ts (lines 19-24) invokes authHelper.removeAuth() to strip credentials from the Git configuration. This approach minimizes the risk of accidental credential exposure in later workflow steps that do not require authenticated Git access.
Source Code Implementation Details
The behavior of persist-credentials is implemented across three key files in the repository:
-
src/input-helper.ts: Parses thepersist-credentialsinput value and assigns it toresult.persistCredentials, making the setting available throughout the checkout process (lines 166-168). -
src/git-source-provider.ts: Orchestrates the decision to retain or remove credentials. The logic checksif (!settings.persistCredentials)to determine whether to immediately remove authentication after checkout (lines 19-24). -
src/git-auth-helper.ts: Implements the actual credential injection and removal logic, manipulating the Git configuration files directly.
Submodule Authentication Implications
The persist-credentials setting directly affects how submodules are authenticated during the checkout process. When persistence is enabled, the action calls gitAuthHelper.configureSubmoduleAuth() to ensure submodule credentials remain available for subsequent Git operations within the same job, as implemented in src/git-source-provider.ts (lines 91-96). If disabled, submodule authentication is temporary and removed immediately after the initial fetch, preventing authenticated access to private submodules in later workflow steps.
Security Considerations and Best Practices
According to the actions/checkout README, storing credentials in $RUNNER_TEMP rather than directly in .git/config provides isolation from the working directory. However, setting persist-credentials: false remains the recommended security posture for workflows that do not perform subsequent authenticated Git operations.
Use persist-credentials: true when subsequent steps need to:
- Push commits or tags to the repository
- Fetch additional private submodules
- Perform authenticated Git operations against the origin
Use persist-credentials: false (default) when:
- The workflow only needs to read the repository code
- Subsequent steps do not require Git authentication
- Minimizing credential exposure is a priority
Configuration Examples
The following workflow demonstrates enabling persistence to push a new tag:
name: Release Workflow
on:
push:
branches: [main]
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Checkout with persistent credentials
uses: actions/checkout@v4
with:
persist-credentials: true
- name: Create and push tag
run: |
git tag "v$(date +%Y%m%d%H%M%S)"
git push origin --tags
For workflows that only require read access, explicitly disable persistence:
name: Secure Build
on: [pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout without credential persistence
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Build application
run: npm ci && npm run build
When using SSH authentication with immediate credential cleanup:
- name: Checkout via SSH
uses: actions/checkout@v4
with:
ssh-key: ${{ secrets.SSH_PRIVATE_KEY }}
persist-credentials: false
Summary
- The
persist-credentialsinput inactions/checkoutdetermines whether authentication tokens remain available after the initial clone operation. - When set to
true, credentials are stored in.git/configand$RUNNER_TEMP, enabling subsequent authenticated Git commands until job completion. - The default value of
falseremoves credentials immediately after checkout, reducing the attack surface for workflows that do not require further authentication. - Implementation resides primarily in
src/input-helper.ts(input parsing),src/git-source-provider.ts(orchestration logic), andsrc/git-auth-helper.ts(credential manipulation). - Submodule authentication behavior is controlled by the same flag, determining whether
configureSubmoduleAuth()maintains credentials for nested repositories.
Frequently Asked Questions
What is the default value of persist-credentials in actions/checkout?
The default value is false. When you do not explicitly set the persist-credentials input, the action automatically removes authentication tokens from the Git configuration immediately after completing the checkout and submodule fetch operations, as handled by the cleanup logic in src/git-source-provider.ts.
When should I set persist-credentials to true?
Set persist-credentials: true when subsequent workflow steps need to perform authenticated Git operations such as pushing commits or tags, fetching additional private submodules, or interacting with the remote repository. When enabled, credentials remain available in $RUNNER_TEMP and .git/config until the job completes and post-job cleanup runs.
Does persist-credentials affect SSH key authentication?
Yes, the persist-credentials input controls the persistence of both HTTPS tokens and SSH keys configured via the ssh-key input. Setting it to false ensures SSH keys are removed from the Git configuration immediately after checkout, while true maintains them for the duration of the job according to the authentication helper implementation.
Is it safe to use persist-credentials: true?
Using persist-credentials: true is safe when you need authenticated Git access in subsequent steps, as credentials are stored in $RUNNER_TEMP rather than the working directory. However, for workflows that only read code, keeping the default false minimizes exposure risk by ensuring credentials exist only for the minimum necessary duration as recommended in the README documentation.
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 →