Add gitsign commit-signature verification - #6121
Conversation
Git-installed skills need the same install-time verification as OCI artifacts (RFC THV-0080). This adds Verifier.VerifyGit: the commit's CMS signature is cryptographically verified over the commit payload via the ietf-cms package (the same library gitsign wraps — importing gitsign itself would compile cosign and the cloud KMS SDKs into the binary), the certificate chain is verified against the Fulcio roots in toolhive-core's embedded trusted material, and the signer identity is extracted with core's normalization. Expected identities from the lock file are compared explicitly — git signatures carry no Sigstore bundle to bind a policy into. Verification time is anchored inside the signing certificate's own validity window, matching gitsign's verifier: Fulcio certificates live for minutes, and proving actual signing time is the transparency log's job. Validating the embedded Rekor proof is a tracked follow-up — the reconstruction helpers are gitsign-internal. git.HeadCommit and gitresolver.ResolveResult gain the signed payload (the encoded commit minus its signature header) so install flows can hand the verifier exactly the bytes the signature covers. Part of #5899. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ietf-cms v0.2.0 mutates a package-level variable during BER decoding, so concurrent ParseSignedData calls race (caught by -race in CI). Signature verification is not hot-path, so serialize the calls with a mutex rather than forking the library the way gitsign does. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## skills-sig/08-verifier #6121 +/- ##
==========================================================
+ Coverage 72.41% 72.52% +0.11%
==========================================================
Files 737 739 +2
Lines 75960 76113 +153
==========================================================
+ Hits 55005 55200 +195
+ Misses 17055 16984 -71
- Partials 3900 3929 +29 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
JAORMX
left a comment
There was a problem hiding this comment.
Panel-review comment on the git half of the verification stack (reviewed together with #6091 and #6129 against RFC THV-0080). One finding, inline: the missing Rekor inclusion-proof validation means the cert-validity anchor at CurrentTime: NotBefore+1min never expires, so the git path's replay window is unbounded — a historical Fulcio cert verifies forever. The PR body already flags this; the inline comment argues for landing it as visibly provisional (marked in the lock like unsigned exceptions) rather than blocking #6129 on vendoring gitsign's Rekor helpers, plus a test that pins current behavior with a TODO to flip when Rekor lands.
Everything else in this PR checked out clean: the smimesign/ietf-cms dependency choice over gitsign's pkg/git (cosign + cloud-KMS closure) is right, the cmsMu serialization of ietf-cms's global BER state is documented and correct, identity extraction reusing core's normalization via SummarizeCertificate avoids re-implementing the GitHub Actions path rules, and the synthetic-CA tests produce real signatures/chains with zero network.
Git verification checks the signature and certificate chain but not yet the transparency-log proof of signing time, leaving the replay window unbounded (an expired Fulcio certificate verifies forever). Per review, that reduced assurance is now visible instead of silent: git-verified provenance carries provisional: true in the lock file — diff-visible like unsigned exceptions — to be removed when Rekor inclusion-proof validation lands. A test pins the expired-certificate behavior with a TODO to flip it then. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Note
Stack 2 of RFC THV-0080 (tracking issue #5899) — stacked on #6091 (verifier wrapper); merges after it, into it, or rebases onto main once #6091 lands. This completes the git half of the verification story that #6084 deliberately deferred.
Summary
Git-installed skills need the same install-time verification as OCI artifacts. This PR adds
Verifier.VerifyGit, full cryptographic verification of gitsign commit signatures:github/smimesign/ietf-cms— the same library gitsign wraps. Importing gitsign's ownpkg/gitwas evaluated and rejected: its package graph compiles cosign and the GCP/Azure/AWS KMS SDKs into the binary (~54 new module entries). ietf-cms was already in our dependency graph.SummarizeCertificateand core'sIdentityFromResult.ErrSignerMismatch): unlike the OCI path there is no Sigstore bundle to bind a policy into. Nil expected is trust-on-first-use, same as OCI.git.HeadCommitandgitresolver.ResolveResultgain the signed payload (encoded commit minus the signature header — the exact bytes the signature covers), so the install flow can hand the verifier signature + payload from one lookup.Type of change
Test plan
task teston the stack tip)task lint-fix, 0 issues)gpgsigheader, present for unsigned commits too). Zero network.Does this introduce a user-facing change?
No — nothing calls
VerifyGityet; enforcement arrives with the install-verification PR.Special notes for reviewers
internal/and reimplementing them pulls in the cosign dependency this PR deliberately avoids. Flagging explicitly since the approved plan wanted Rekor validation in-stack — this PR ships the signature+chain half; happy to discuss whether the follow-up should block PR11.verifyGitSignaturetakes injectable pools; the exportedVerifyGitpins the embedded Fulcio roots).Generated with Claude Code