Skip to content

checkout-isolated: add a pre-checkout git-config isolation action - #4

Merged
kei-nan merged 1 commit into
mainfrom
jk/checkout-isolated
Aug 16, 2026
Merged

checkout-isolated: add a pre-checkout git-config isolation action#4
kei-nan merged 1 commit into
mainfrom
jk/checkout-isolated

Conversation

@kei-nan

@kei-nan kei-nan commented Aug 16, 2026

Copy link
Copy Markdown
Collaborator

Problem

Git-config isolation only helps if it runs before a checkout. That makes it
impossible to package as a local (./) composite action in a consuming repo:
GitHub resolves local actions from the workspace, and the workspace is empty
until something checks out. A consumer that factored its triplicated
isolate-then-checkout block into ./.github/actions/checkout-isolated got
Can't find 'action.yml' on a fresh runner, in every job that used it.

Consumed from here it works, because the runner downloads a remote action
without needing a workspace at all.

What this adds

.github/actions/checkout-isolated — the isolate-then-checkout block consumers
already run inline ahead of a checkout on self-hosted runners:

  • points git at a clean, workflow-owned global config exported to every later
    step in the job, ignores system config, and keeps only safe.directory, so no
    leftover key that maps an event or path to an executable (hooks, fsmonitor,
    attributesFile filters, templateDir, url.insteadOf, credential.helper,
    sshCommand, …) can take effect;
  • removes a reused .git, which carries the same state locally;
  • then checks out, with ref / fetch-depth / persist-credentials as inputs.

persist-credentials defaults to false rather than actions/checkout's true:
a job that pushes should mint a scoped token and pass it explicitly.

Nothing existing changes — this only adds a new unit plus one README row, so
moving v1 onto it is behaviour-preserving for current consumers.

🤖 Generated with Claude Code


Note

Low Risk
Additive CI plumbing only; no changes to existing workflows or runtime product code, though mis-ordering the step in a consumer job would weaken the intended hardening.

Overview
Introduces checkout-isolated, a composite action meant as a job’s first step on persistent self-hosted runners. Before actions/checkout@v6, it writes a minimal global git config under RUNNER_TEMP, exports GIT_CONFIG_GLOBAL / GIT_CONFIG_NOSYSTEM (and nulls system config) for the rest of the job, sets safe.directory '*', and rm -rf .git so reused workspace state cannot influence checkout.

Exposes ref, fetch-depth (default 1), and persist-credentials (default false, unlike stock checkout). The action is documented in the README Shared CI utilities table with a note that it must be consumed from this repo (not as a local ./ action) because isolation has to run before any workspace checkout.

Reviewed by Cursor Bugbot for commit a6d3c9d. Bugbot is set up for automated code reviews on this repo. Configure here.

Hardening a checkout has to happen before that checkout runs, which rules out a
local (`./`) action in the consuming repo: GitHub resolves those from the
workspace, and the workspace is empty until something checks out — a consumer
that tried it got "Can't find action.yml" on a fresh runner. Downloaded from
here, the runner needs no workspace for it.

The step itself is the block consumers already run inline ahead of a checkout on
self-hosted runners, with the checkout's ref, depth and credential persistence
as inputs. persist-credentials defaults off, unlike actions/checkout.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@kei-nan kei-nan self-assigned this Aug 16, 2026
@kei-nan
kei-nan requested a review from Itzikvaknin August 16, 2026 12:59
} >> "$GITHUB_ENV"
rm -rf .git

- uses: actions/checkout@v6

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Semgrep identified a blocking 🔴 issue in your code:
GitHub Actions step uses a mutable tag or branch reference. Tags and branch names can be silently repointed by the action owner, enabling supply-chain attacks — as seen in the trivy-action and kics-github-action compromises. Pin the reference to a full 40-character commit SHA instead, e.g. uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608.

To resolve this comment:

🔧 No guidance has been designated for this issue. Fix according to your organization's approved methods.

💬 Ignore this finding

Reply with Semgrep commands to ignore this finding.

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by github-actions-mutable-action-tag.

You can view more details about this finding in the Semgrep AppSec Platform.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/ar actions/checkout is GitHub's own first-party action, and every one of the eight other checkout pins in this repo (ci.yml, codex-agent.yml, flaky-*.yml, flaky-filter, flaky-record-results, link-check.yml, spellcheck.yml) is the same @v6 version tag. SHA-pinning only this one would diverge from all of them and then drift, since the repo has no process for bumping SHA pins — the deliberate SHA pin here is openai/codex-action, a third party. The rule's threat model (the action owner silently repointing the tag) is GitHub itself, which the runner and the API already trust wholesale.

@kei-nan
kei-nan merged commit a5066ba into main Aug 16, 2026
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant