Skip to main content
Every channel entry verifies offline — the bundle carries its own trust material, and each entry ships these commands as a ready-to-run VERIFY.md with its own file names in. The chain: channel.pub reaches you out of band → it verifies entry.jsonentry.json names the sha256 of every evidence file and every image digest, so one signature seals the bundle → the chart references those same digests → your Kyverno pins the same key at admission. 1 — The entry is signed. Steps 2–4 add no signatures; they recompute hashes against this sealed record.
2 — The evidence bundle is intact. Recompute the sha256 of every file in evidence/ and compare to entry.json — a nine-line script in VERIFY.md. A mismatch is a rejection. 3 — The source provenance is real. Proves the source archive was built from the stated public repository at the stated commit, attested by the build platform’s identity, not Vexa’s word.
4 — The digest set is the validated one. The digest map’s sha256 must equal the pin inside the delivery receipt from Vexa’s own production run of this release. 5 — The images carry the channel signature. Same check your admission layer runs on every pod, same key; signatures live in the registry in the legacy format, with no transparency-log entry.
COSIGN_REPOSITORY is what points cosign at the signature repository instead of alongside the image; without it the command returns no signatures found. It is the same value your install.sh --signature-repository carries, and the entry’s own VERIFY.md fills it in for you.

On a PLATFORM ESTATE entry

An estate entry — one carrying an estate block, published from a running cluster rather than cut from a release tag — has no source archive, no SLSA provenance and no delivery receipt, so steps 3 and 4 do not apply and vexa-verify says so out loud instead of skipping quietly. Each absence is named in the signed document, so it is a statement you can hold us to:
What replaces them is a different claim, not a weaker one: the digest set is captured from the running cluster, per image, with its own receipt, and validated against a mandatory validation_contract named and hashed in the entry. Your contract decides whether the absences are acceptable, via forbid_absent_evidence — an estate-shaped contract lists validation_contract there, so an entry that declared that away is refused, and an OSS-shaped contract pointed at an estate refuses it correctly on its own terms. Annotated worked form: kit/verify/policy.example.yaml.

If step 1 fails on the bundle format

An entry signed by an older cosign carries a legacy bundle, rejected with ecdsa: Invalid IEEE_P1363 encoded bytes — a message that looks like a corrupt signature and is not one. Try:

Read before you accept

evidence_absent — kinds this release does not carry, each with a reason. break_glass — who authorised an incomplete chain, and why; a release with gaps and no break-glass record should be rejected by your verifier. The delivery receipt — which images served production traffic and which were validated in other harnesses; the claim is never rounded up. Verification is digest- and signature-based, so it holds whichever registry served the bytes, your own mirror included. See isolated networks. Next: The station gate · For your auditors