The persist-credentials input of actions/checkout decides whether the repository token stays configured for later git commands in the job. It defaults to true. Setting it to false removes that convenience, so later steps cannot push with the checkout token. Release and test jobs rarely need it.
What the documentation says
The checkout README lists the input as whether to configure the token or SSH key with the local git config, default true. That lets later scripts run authenticated git commands such as fetch and push. The post-job cleanup step removes the token. The README notes that in version 6, credentials are stored in a separate file under the runner temp folder instead of directly in the git config. Which version you use affects where the token sits, so read the notes for the version you pin.
To opt out, set persist-credentials to false.
Why security people care
GitHub Security Lab's article on pwn requests points out that with the default, the repository token is written to disk where later steps can read it. If a later step runs untrusted code, for example an install script in a dependency, that code can use the token. Setting persist-credentials to false narrows that. It is not a full defense, because other routes to the token exist, but it removes an easy one.
When to set false
| Job type | Set false? |
|---|---|
| Run tests | Yes |
| Build and publish with OIDC or a registry token | Yes |
| Lint and scan | Yes |
| A job that commits back to the repository | No, or use a separate token deliberately |
The README also recommends contents read permission unless you provide other authentication through the token or ssh-key inputs.
A safe default snippet
permissions:
contents: read
steps:
- uses: actions/checkout@v5
with:
persist-credentials: false
Pair this with a job level permissions block. See least privilege GITHUB_TOKEN for a release workflow.
What may break
- Steps that run git push or git commit with the checkout token will fail with an authentication error.
- Tools that tag releases or update changelogs from CI need another way to authenticate. Use a separate, narrowly scoped credential in only that job, or a GitHub App token.
- Submodule fetches that rely on the same token may need explicit setup.
If a job breaks, fix it by giving only that job what it needs. Do not set the option back to true everywhere.
A short rollout
- Search your workflows for actions/checkout.
- Add persist-credentials false everywhere.
- Run the workflows and fix the few jobs that truly push.
- Add the workflows folder to CODEOWNERS so nobody reverses it quietly.
- Review pull_request_target risks.
Safeguard can enforce policies and gates on pull requests, and the free scan at gold.safeguard.sh/scan covers your dependencies.
Quick check
Does persist-credentials false make a workflow safe from untrusted code?
No. It removes one easy route to the token. You still need least privilege permissions and to avoid running untrusted code in privileged jobs.
Is the default true?
Yes, per the checkout README.
Sources
Last reviewed: 19 October 2026.