Sigstore & TUF Integration#
Kyverno uses the Sigstore ecosystem for image signature and attestation verification, with The Update Framework (TUF) providing authenticated distribution of the cryptographic trust roots needed for that verification. Two policy surfaces are involved:
ClusterPolicy/Policy(cpol) — the legacy policy engine withimageVerifyrulesImageValidatingPolicy(ivpol) — the newer CEL-based image verification policy
Both surfaces share the same underlying Sigstore/TUF libraries but have separate cosign verifier implementations.
Key Dependencies#
| Package | Version | Role |
|---|---|---|
github.com/sigstore/cosign/v3 | v3.0.6 | Core cosign verification logic |
github.com/sigstore/sigstore-go | v1.1.4 | Sigstore bundle verification (Sigstore GA protocol) |
github.com/sigstore/sigstore | v1.10.8 | TUF client, Fulcio roots, Rekor pub keys |
github.com/sigstore/rekor | v1.5.2 | Transparency log client |
github.com/theupdateframework/go-tuf/v2 | v2.4.1 | TUF metadata client (transitive, see CVEs below) |
Verification Flow#
For ivpol (sigstore-go-based bundle verification):
- Parse image reference and fetch OCI referrers for the image digest.
- Filter referrers by
application/vnd.dev.sigstore.bundleartifact type; deserialize each as abundle.Bundle. - Fetch
trusted_root.jsonfrom the TUF client viagetTrustedRoot. - Build a
verify.SignedEntityVerifierfrom the trusted root and callverifier.Verify(bundle, policy)for each bundle. - For attestations, filter bundles by
in-totopredicate type and decode the DSSE envelope .
Transparency log and SCT checks are toggled via buildVerifyOptions: passing verify.WithTransparencyLog(1) requires at least one Rekor entry; verify.WithObserverTimestamps(1) requires an SCT. These correspond to the ignoreTlog / ignoreSCT options surfaced in policy specs.
For cpol (classic cosign verification):
checkOptions in opts.go assembles a cosign.CheckOpts struct:
- Calls
initializeTufto bootstrap the TUF client before any other Sigstore infrastructure is contacted. - Fetches Rekor public keys and CTLog public keys via
getRekor. - Fetches Fulcio root/intermediate CAs via
getFulcio. - Sets
opts.Offline = truewhen Rekor public keys are available but no live Rekor client is configured .
A mutex (tufMu) serializes concurrent TUF initializations to prevent race conditions .
TUF Initialization#
TUF is initialized in two different contexts:
1. Startup (global, for cpol): setupSigstoreTUF in cmd/internal/tuf.go is called at process startup when config.UsesCosign() is true. It reads the TUF root from a file/URL (tufRoot) or base64-encoded string (tufRootRaw), then calls tuf.Initialize(ctx, tufMirror, tufRootBytes). This is gated by the --enableTuf flag (default false).
2. Per-verification (ivpol): initializeTuf is called inline during checkOptions. If the policy's .spec.tuf is non-nil, it uses the policy-specified mirror and root; otherwise it falls back to tuf.DefaultRemoteRoot with a nil root (public Sigstore).
Startup flags (defined in cmd/internal/flag.go):
| Flag | Default | Description |
|---|---|---|
--enableTuf | false | Enable TUF for private Sigstore deployments |
--tufMirror | tuf.DefaultRemoteRoot | Alternate TUF mirror URL |
--tufRoot | "" | Path or URL to alternate root.json |
--tufRootRaw | "" | Base64-encoded alternate root.json |
Trusted Root Resolution#
Both the cpol and ivpol paths resolve trusted_root.json from the TUF cache via the same pattern: call tuf.NewFromEnv(ctx) to get a client, then tufClient.GetTarget("trusted_root.json"), and pass the bytes to root.NewTrustedRootFromJSON . This TrustedRoot object bundles all certificate transparency log public keys, Rekor log IDs, and Fulcio CA certificates needed to verify a Sigstore bundle without contacting live infrastructure.
Certificate Chain Security (CVE-2026-32280)#
opts.go enforces maxIntermediateCerts = 10 on user-supplied certificate chains before expensive ASN.1 parsing, mitigating a DoS vector via unbounded crypto/x509 chain building .
TUF Dependency CVE History#
github.com/theupdateframework/go-tuf/v2 is a transitive dependency (via cosign and sigstore-go) that has required explicit pinning to overcome vulnerabilities:
| CVE | Affected versions | Impact | Fixed in PR |
|---|---|---|---|
| CVE-2026-23992 | go-tuf/v2 2.0.0–2.3.0 | Signature threshold can be set to 0, disabling cryptographic verification | #15571 → v2.3.1 |
| CVE-2026-24686 | go-tuf/v2 < 2.4.1 | Path traversal via unsanitized repoName in TUF map file, allowing writes outside the cache directory | #15579 → v2.4.1 |
Both fixes override transitive version selection by adding the patched version as a direct require entry, leveraging Go MVS to ensure the pinned version wins over older transitive references .
Source Map#
| Path | Purpose |
|---|---|
cmd/internal/tuf.go | Global TUF init at startup |
cmd/internal/flag.go | --enableTuf and related CLI flags |
pkg/image/verifiers/cpol/cosign/sigstore.go | cpol bundle verification & trusted root fetch |
pkg/image/verifiers/ivpol/cosign/opts.go | ivpol CheckOpts assembly, per-policy TUF init, Rekor/Fulcio wiring |