Summary
skills-init's full-clone-then-checkout path (CloneGit in go/core/internal/skillsinit/git.go) always fails when Full: true is used with a commit SHA ref, because the checkout command passes the SHA as a pathspec rather than a revision:
if err := runGitIn(ref.Dest, "checkout", "--", ref.Ref); err != nil {
The -- separator before ref.Ref forces git to interpret ref.Ref as a pathspec, not a commit-ish. Since no file in the repo is literally named after the 40-char SHA, this always fails with:
error: pathspec '<sha>' did not match any file(s) known to git
Reproduction
git init repo && cd repo
echo x > f && git add f && git commit -m init
SHA=$(git rev-parse HEAD)
git checkout -- "$SHA"
# error: pathspec '<sha>' did not match any file(s) known to git
git checkout "$SHA"
# Note: switching to '<sha>'. ... (works correctly)
Confirmed against the released v0.9.12 tag (same code present on main as of this report) — the bug affects every deployment using a gitRefs[].full: true entry pinned to a commit SHA, which is exactly the pattern the skills-init docs recommend for supply-chain-safe SHA pinning (full clone + immutable SHA, as opposed to the depth-1 --branch path which only accepts mutable branch/tag names).
Impact
Any Agent CRD that references a skill via a SHA-pinned full: true git ref will have its skills-init init container crash-loop forever with Init:Error, because the container restarts and re-runs from a directory that was already (partially) cloned on the previous attempt, compounding with a second bug: retries against an already-cloned dest fail with destination path ... already exists and is not an empty directory before ever reaching the checkout step. Users relying on SHA pinning for supply-chain integrity have no working code path today.
Suggested fix
Drop the -- separator (or place it after the ref) in the checkout call:
if err := runGitIn(ref.Dest, "checkout", ref.Ref, "--"); err != nil {
ref.Ref is already validated upstream as a 40/64-char hex string when Full is true, so there's no argument-injection risk from treating it as a revision instead of a pathspec.
Environment
- kagent skills-init image:
v0.9.12
- Discovered while live-verifying a kagent Agent CRD using a SHA-pinned skill in a lab cluster.
Summary
skills-init's full-clone-then-checkout path (CloneGitingo/core/internal/skillsinit/git.go) always fails whenFull: trueis used with a commit SHA ref, because the checkout command passes the SHA as a pathspec rather than a revision:The
--separator beforeref.Refforces git to interpretref.Refas a pathspec, not a commit-ish. Since no file in the repo is literally named after the 40-char SHA, this always fails with:Reproduction
Confirmed against the released
v0.9.12tag (same code present onmainas of this report) — the bug affects every deployment using agitRefs[].full: trueentry pinned to a commit SHA, which is exactly the pattern the skills-init docs recommend for supply-chain-safe SHA pinning (full clone + immutable SHA, as opposed to the depth-1--branchpath which only accepts mutable branch/tag names).Impact
Any Agent CRD that references a skill via a SHA-pinned
full: truegit ref will have itsskills-initinit container crash-loop forever withInit:Error, because the container restarts and re-runs from a directory that was already (partially) cloned on the previous attempt, compounding with a second bug: retries against an already-cloneddestfail withdestination path ... already exists and is not an empty directorybefore ever reaching the checkout step. Users relying on SHA pinning for supply-chain integrity have no working code path today.Suggested fix
Drop the
--separator (or place it after the ref) in the checkout call:ref.Refis already validated upstream as a 40/64-char hex string whenFullis true, so there's no argument-injection risk from treating it as a revision instead of a pathspec.Environment
v0.9.12