Summary
🦾 Written with LLM assistance [claude-opus-4-6]
💪 Reviewed by a human before submission
Add an optional trusted_root_digest field to VerificationConfig that pins the custom trusted_root.json file by content hash, detecting post-provisioning file substitution.
Context
PR #788 introduced trusted_root support for private Sigstore instances. The threat model (THR02.MIT05) acknowledges that the user-supplied file has no TUF integrity protection -- file permissions and access control are the operator's responsibility.
During review of #788, we identified that digest pinning would address the most plausible attack vector (post-provisioning file replacement) without requiring operators to run TUF infrastructure. An attacker who replaces the trusted root file must also update the digest in complytime.yaml -- a separate file, typically version-controlled and reviewed.
Proposed Design
verification:
issuer: https://dex.internal
identity: signer@internal
trusted_root: /path/to/trusted_root.json
trusted_root_digest: sha256:a1b2c3d4e5f6...
- Add
TrustedRootDigest string field to VerificationConfig in internal/complytime/config.go
- At verifier construction time (before calling
root.NewTrustedRootFromPath), read the file, compute its SHA-256 digest, and compare against the pinned value
- If the digest does not match, return an error (fail-closed)
- If
trusted_root_digest is empty, skip the check (backward compatible)
- Validate digest format at config validation time using existing
ValidateDigest() from internal/cache/state.go
Existing Patterns
This follows established codebase conventions:
opencontainers/go-digest is already vendored and used for OCI digest validation
ValidateDigest() in internal/cache/state.go:18-31 provides format validation
PolicyRef.Digest in internal/complytime/config.go uses the same pinning pattern for OCI references
Limitations
Related
Summary
Add an optional
trusted_root_digestfield toVerificationConfigthat pins the customtrusted_root.jsonfile by content hash, detecting post-provisioning file substitution.Context
PR #788 introduced
trusted_rootsupport for private Sigstore instances. The threat model (THR02.MIT05) acknowledges that the user-supplied file has no TUF integrity protection -- file permissions and access control are the operator's responsibility.During review of #788, we identified that digest pinning would address the most plausible attack vector (post-provisioning file replacement) without requiring operators to run TUF infrastructure. An attacker who replaces the trusted root file must also update the digest in
complytime.yaml-- a separate file, typically version-controlled and reviewed.Proposed Design
TrustedRootDigest stringfield toVerificationConfigininternal/complytime/config.goroot.NewTrustedRootFromPath), read the file, compute its SHA-256 digest, and compare against the pinned valuetrusted_root_digestis empty, skip the check (backward compatible)ValidateDigest()frominternal/cache/state.goExisting Patterns
This follows established codebase conventions:
opencontainers/go-digestis already vendored and used for OCI digest validationValidateDigest()ininternal/cache/state.go:18-31provides format validationPolicyRef.Digestininternal/complytime/config.gouses the same pinning pattern for OCI referencesLimitations
Related