actions/checkout v7: what the fork pull request block changes
Action for checking out a repo
At a glance
- What is it?
- GitHub's checkout action now refuses to check out fork pull request code under pull_request_target or workflow_run unless you set allow-unsafe-pr-checkout. Here is the mechanism, the install path, and where the action stops being the right tool.
- Who is it for?
- Use actions/checkout when a workflow needs repository contents in $GITHUB_WORKSPACE, especially if you want sparse-checkout, a shallow fetch-depth, or a token that persists for later git commands. Do not use it as a general git client for arbitrary remotes, and do not expect contributions: the README states the project is not taking them.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 9 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 27, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What actions/checkout is for, and who actually needs it
Every GitHub Actions job starts on a runner with an empty workspace. The README states the action checks out your repository under $GITHUB_WORKSPACE so the workflow can access it. That single sentence defines the audience: anyone whose job needs source files, a build script, a test suite, or a git history to run against. If your job only calls an external API or publishes an artifact built elsewhere, you do not need it, and adding it costs a fetch.
The default behaviour is deliberately narrow. Only a single commit is fetched by default, for the ref or SHA that triggered the workflow. That is a real design decision with consequences: a job that runs git log, computes a changelog, or depends on tags needs fetch-depth: 0, because the default history is one commit deep. The README points at the GitHub documentation to learn which commit $GITHUB_SHA points to for different events, which is the part people get wrong most often when they assume the default ref matches their branch.
The action also handles the case where Git is not usable. When Git 2.18 or higher is not in your PATH, it falls back to the REST API to download the files. That fallback exists for runners and container images that ship without a recent git, and it means the action is not simply a wrapper around a git binary.
The v7 change: refusing fork pull request code by default
The headline in the v7 release notes is not a performance improvement. Checkout now refuses to check out fork pull request code by default when the workflow is triggered by pull_request_target or workflow_run. The README explains the reasoning directly: those triggers run with the base repository's GITHUB_TOKEN, secrets, and runner access, where executing a fork's code commonly leads to pwn request vulnerabilities. This is a breaking change for any repository that relied on the old behaviour, and it is the right kind of breaking change, because the old behaviour was a security footgun that many workflows inherited by copy and paste.
The opt-in is explicit and named for what it does: set allow-unsafe-pr-checkout: true. The README links to guidance on securely using pull_request_target before you do that. If a workflow of yours suddenly fails after upgrading to v7, this default is the first thing to check, not the ref or the token.
The v7 release also migrated the action to ESM to support new versions of the @actions/* packages and updated direct and transitive dependencies, including security fixes for known vulnerabilities. Those are maintenance items rather than features, but they explain why the major version moved.
Credentials, cleanup, and the v6 storage change
By default the action persists credentials so that later steps can run authenticated git commands such as git fetch and git push. In v6 that storage moved: persist-credentials now stores credentials in a separate file under $RUNNER_TEMP instead of directly in .git/config. The README states no workflow changes are required and that authenticated git commands continue to work. The token is removed during post-job cleanup, and persist-credentials: false opts out entirely.
One constraint from that change is easy to miss. Running authenticated git commands from a Docker container action requires Actions Runner v2.329.0 or later. If you pin an older self-hosted runner, the credential file under $RUNNER_TEMP is not visible to the container in the way the old .git/config was, and your git commands inside that container will fail authentication.
The SSH path is separate and stricter. ssh-strict defaults to true, which the README describes as adding StrictHostKeyChecking=yes and CheckHostIP=no to the SSH command line. Additional hosts go in ssh-known-hosts, and the public key for github.com is always implicitly added.
Adding actions/checkout to a workflow and running a first sparse checkout
There is no package to install. The action is consumed from a workflow file, and the README gives the usage block for actions/checkout@v7. A minimal job that only needs the default single commit looks like this.
- uses: actions/checkout@v7
with:
repository: ''
ref: ''
token: ''The reader should see the repository contents appear in $GITHUB_WORKSPACE before later steps run, with one commit of history. Those three inputs are the first entries in the README's usage block, and leaving them empty means the defaults apply: the repository that triggered the workflow, the ref or SHA for that event, and ${{ github.token }}.
If your job needs history or tags, add the inputs rather than scripting a fetch. fetch-depth: 0 fetches all history for all branches and tags, and fetch-tags: true fetches tags even when fetch-depth is greater than 0.
- uses: actions/checkout@v7
with:
fetch-depth: 0
fetch-tags: trueFor large monorepos the more interesting inputs are sparse-checkout and filter. The README notes that filter overrides sparse-checkout if set, and that sparse-checkout takes patterns separated by new lines, with sparse-checkout-cone-mode defaulting to true.
- uses: actions/checkout@v7
with:
sparse-checkout: |
packages/api
packages/sharedThe reader should see only those paths materialised in the workspace. If you also set filter, the sparse patterns are ignored, which is the documented precedence and a common source of confusion.
Where actions/checkout is the wrong tool
The action checks out a repository into the workspace of a job. It is not a general purpose git client. If you need to clone several unrelated repositories into distinct directories, you must either use the path input to place each one under $GITHUB_WORKSPACE or run git clone yourself; the action's repository input names one repository with owner, defaulting to ${{ github.repository }}. For a matrix that pulls a dozen third party repositories, hand written git commands are usually clearer than a wall of checkout steps with path overrides.
The clean input is another place where defaults surprise people. It defaults to true, and the README describes it as running git clean -ffdx and git reset --hard HEAD before fetching. That is exactly what you want on a fresh runner and exactly what you do not want if an earlier step in the same job produced files you intended to keep. Anyone who generates code, patches, or fixtures before checkout and then wonders where they went should set clean: false or reorder the steps.
The maintainer position is also a limitation. The README states plainly that the project is not taking contributions right now, that questions and support requests go to Community Discussions, that high priority bugs can be reported there or to support, and that security issues follow security.md. The README adds that security updates will still be provided and major breaking changes fixed during this period. So fixes arrive, but outside contributions do not, and a feature you want will not land through a pull request.
Finally, the runtime floor matters. v5 moved to the node24 runtime and requires a minimum Actions Runner version of v2.327.1. v6 raised the bar for container actions to v2.329.0. Self-hosted fleets pinned below those versions cannot run these major versions at all.
The alternative: skipping checkout and driving git directly
The obvious alternative is not another checkout action. It is a run step that calls git yourself. The difference is control versus defaults. A raw git command gives you any remote, any depth, any refspec, and no opinion about credentials, but you then own the token setup, the cleanup, the host key handling, and the fallback when git is absent. actions/checkout packages those decisions: token or ssh-key configuration, cleanup in a post-job step, ssh-strict host key checking, and a REST API download path when Git 2.18 or higher is not in PATH.
The practical split is this. If your job checks out the repository that triggered the workflow, or one repository named explicitly, use the action and let it manage the credential lifecycle. If your job needs arbitrary clone topologies, submodules fetched in unusual ways, or git behaviour the action does not expose, write the git commands and accept that you are now responsible for removing the token when the job ends. The action's own README frames the credential handling as its value: the token is configured with the local git config so your scripts can run authenticated git commands, and the post-job step removes it.
Maintenance, upgrades, and the MIT licence
The repository is not archived, and the last push was on 2026-09-21. Recent releases include v7.0.1, v6.1.0, and v5.1.0, all published on 2026-07-20, which shows that the older major lines receive releases alongside the current one. That matters if you are not ready to move to v7: staying on v6 still gets patches.
Upgrade cost is concentrated in two places. Moving to v7 forces you to audit every workflow triggered by pull_request_target or workflow_run, because the default now refuses fork pull request code; the README gives allow-unsafe-pr-checkout: true as the opt-in. Moving to v6 or v5 forces a runner version check, v2.329.0 for authenticated git in Docker container actions and v2.327.1 for the node24 runtime. The package.json declares engines.node as >=24, which is about building the action, not consuming it.
The action is MIT licensed, and the repository carries a .licensed.yml plus a .licenses/ directory, which indicates the project tracks its dependency licences. MIT is permissive, so embedding the action in a commercial workflow raises no licensing question in itself; the dependency licences recorded in .licenses/ are a separate matter, and if your organisation reviews third party licences, that directory is where to look rather than the top level LICENSE file.
Editorial conclusion
Use actions/checkout when a workflow needs repository contents in $GITHUB_WORKSPACE, especially if you want sparse-checkout, a shallow fetch-depth, or a token that persists for later git commands. Do not use it as a general git client for arbitrary remotes, and do not expect contributions: the README states the project is not taking them. Before upgrading to v7, check every workflow triggered by pull_request_target or workflow_run, because the default now refuses fork pull request code and the fix is either allow-unsafe-pr-checkout: true or a redesign of the trigger.
Frequently asked questions
What does actions/checkout do in a GitHub Actions workflow?
It checks out your repository under $GITHUB_WORKSPACE so the workflow can access it. By default it fetches only a single commit, for the ref or SHA that triggered the workflow.
How do I use actions/checkout to fetch the full git history?
Set fetch-depth: 0, which the README describes as fetching all history for all branches and tags. Add fetch-tags: true if you also need tags when fetch-depth is greater than 0.
Why does actions/checkout v7 refuse to check out fork pull request code?
Because pull_request_target and workflow_run run with the base repository's GITHUB_TOKEN, secrets, and runner access, where executing a fork's code commonly leads to pwn request vulnerabilities. You can opt in with allow-unsafe-pr-checkout: true after reviewing the linked risks.
Where are credentials stored when persist-credentials is enabled?
In v6 and later they are stored in a separate file under $RUNNER_TEMP instead of directly in .git/config, and the README states no workflow changes are required. The token is removed during post-job cleanup.
Does actions/checkout work if git is not installed on the runner?
Yes. When Git 2.18 or higher is not in your PATH, the action falls back to the REST API to download the files.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/actions-checkout)