sigstore/cosign
pkg/policy
pkg/policy/ is the bridge between cosign's verifier and a policy language (CUE or Rego). It runs after the cryptographic checks have passed — once we know an attestation is genuine, this is where we enforce business rules about its predicate.
Layout
pkg/policy/
├── attestation.go # AttestationToPayloadJSON, EvaluatePolicyAgainstJSON
├── eval.go # CUE/Rego dispatcher
├── errors.go # ErrNoMatchingAttestations etc.
├── attestation_test.go
├── eval_test.go
├── fuzz_test.go
└── testdata/ # sample CUE/Rego policies + payloadsThe companion language adapters live under pkg/cosign/cue/ and pkg/cosign/rego/.
Key functions
// pkg/policy/attestation.go
func AttestationToPayloadJSON(ctx context.Context, predicateType string,
verifiedAttestation PayloadProvider) ([]byte, string, error)
// pkg/policy/eval.go
func EvaluatePolicyAgainstJSON(ctx context.Context, name, policyType string,
policyBody string, jsonBytes []byte) errorAttestationToPayloadJSON:
- Takes a verified attestation (
oci.Signature, but the function only depends onPayload()). - Decodes the DSSE envelope and the inner in-toto Statement.
- Filters by
predicateType— returning empty if the predicate type doesn't match what the caller asked for. - Returns the predicate JSON bytes ready to feed to a policy engine, plus the actual predicate type (so callers can write helpful error messages on near-miss type names).
EvaluatePolicyAgainstJSON dispatches on policyType:
"cue"→pkg/cosign/cue/cue.go(usescuelang.org/go)."rego"→pkg/cosign/rego/rego.go(usesgithub.com/open-policy-agent/opa).- anything else → typed error.
Where it's wired
The CLI side lives in cmd/cosign/cli/verify/verify_attestation.go (and verify_blob_attestation.go). The flow:
graph LR
A[cosign verify-attestation] -->|verify cryptography| B[oci.Signature]
B -->|AttestationToPayloadJSON| C[predicate JSON]
C -->|EvaluatePolicyAgainstJSON --policy| D{Pass?}
D -->|yes| E[print Statement on stdout]
D -->|no| F[non-zero exit]If --policy is not supplied, the cryptographic check alone is enough and pkg/policy is skipped.
Why two policy languages?
Both came in early when neither was the obvious winner for supply-chain policy. They're functionally equivalent for the in-toto-predicate use case; pick whichever the rest of your stack already speaks:
- CUE — schema + constraints in one syntax. The
pkg/cosign/cue/testdata/examples lean on its strong typing for SLSA-style attestations. - Rego — OPA's language. Closer to traditional policy engines (Kubernetes admission, Conftest, etc.).
Both adapters emit string-typed errors, which EvaluatePolicyAgainstJSON wraps with the policy name so verifier output names which policy failed.
Cross-references
- Predicate type → URI mapping:
cmd/cosign/cli/options/predicate.go::PredicateTypeMap. - The verifier-side trigger: CLI / Verification / verify-attestation.
- Statement assembly on the signing side:
pkg/cosign/attestation/attestation.go.
Key source files
| File | Purpose |
|---|---|
pkg/policy/attestation.go |
DSSE → predicate JSON extraction |
pkg/policy/eval.go |
CUE/Rego dispatch |
pkg/policy/errors.go |
Sentinel errors |
pkg/cosign/cue/cue.go |
CUE evaluator |
pkg/cosign/rego/rego.go |
Rego evaluator |
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.