Verify a Release
Verifying a release happens at two layers, and you should do both before you trust a deployment:
- The release artifacts — the checksums, manifests, attestation policies, and container metadata published with a GitHub release. Verify them with the repo’s scripts: SHA-256 checksums plus cosign (Sigstore) signatures that pin who built them.
- A running instance — a live KMS or merod node. Verify its attestation with the public web verifier: it pulls a fresh quote, appraises it through Intel Trust Authority, and compares its measurements against the release policy.
The artifact scripts prove the release you downloaded is authentic and untampered; the web verifier proves a specific live instance is running that release. See Verification for the meaning of each check.
Layer 1 — verify the release assets
Section titled “Layer 1 — verify the release assets”The combined entry point takes a version and verifies both the KMS and the node-image asset sets for it:
scripts/release/verify-release-assets.sh <version><version> may be a bare X.Y.Z or a full tag; the script normalizes it and
derives the two release tags it needs:
# All of these verify the 2.3.51 KMS and node-image asset sets:scripts/release/verify-release-assets.sh 2.3.51scripts/release/verify-release-assets.sh mero-kms-v2.3.51scripts/release/verify-release-assets.sh mero-tee-v2.3.51Internally it calls the two per-artifact verifiers, which you can also run directly against a single asset set:
scripts/release/verify-kms-phala-release-assets.sh mero-kms-v<version>scripts/release/verify-node-image-gcp-release-assets.sh mero-tee-v<version>What each script checks
Section titled “What each script checks”- Downloads the signed assets for the tag — checksums file, release
manifest, attestation policies (including the per-profile
kms-phala-attestation-policy.<profile>.jsonfiles), container metadata, SBOMs, and the release archives. - Verifies SHA-256 checksums — normalizes
kms-phala-checksums.txtand runssha256sum -c, then cross-checks each archive hash against the release manifest so the checksums file and manifest must agree. - Verifies cosign signatures — for every signed asset it runs
cosign verify-blobagainst the asset’s.sigand.pem, pinning the signer identity and OIDC issuer:- identity (default): the release workflow, e.g.
^https://github.com/calimero-network/mero-tee/.github/workflows/release-kms-phala.yaml@refs/heads/master$(the node-image script pinsrelease-node-image-gcp.yaml). - OIDC issuer (default):
https://token.actions.githubusercontent.com.
- identity (default): the release workflow, e.g.
A non-zero exit means the release is incomplete or tampered — do not deploy it.
Requirements
Section titled “Requirements”The KMS verifier needs jq, cosign, sha256sum, awk, basename, curl,
and git on PATH. gh (GitHub CLI) is optional — the script uses it when
present and falls back to curl otherwise. For higher API rate limits or
private repos, export GH_TOKEN (or GITHUB_TOKEN).
Layer 2 — verify a live instance with the web verifier
Section titled “Layer 2 — verify a live instance with the web verifier”The public attestation verifier is a small web app backed by a stateless
/api/verify function. It has two routes:
| Route | Verifies | Reachability |
|---|---|---|
/kms |
a Phala KMS instance, by URL | KMS must serve POST /attest over HTTPS |
/mero-tee |
a merod node or a KMS | node must serve POST /admin-api/tee/attest |
On each route you enter the instance URL and, optionally, a release tag and (for KMS) a profile to compare measurements against. The backend generates a fresh 32-byte nonce, fetches the attestation, appraises the quote through Intel Trust Authority, verifies the returned JWT against Intel’s JWKS, and compares the measurements and compose-hash against the published release policy. The mechanics of each check are covered in Verification.
Deep-link parameters
Section titled “Deep-link parameters”Both routes read their inputs from query parameters, so you can share a pre-filled verification link. A KMS deep link:
/kms?kms_url=https://your-kms.phala.network&release_tag=mero-kms-v2.3.51&profile=locked-read-onlykms_url— the KMS base URL (required to auto-run).release_tag— release to compare against, e.g.mero-kms-v2.3.51(optional).profile—debug,debug-read-only, orlocked-read-only(optional).
A node deep link on /mero-tee:
/mero-tee?node_url=http://34.65.123.45:80&release_tag=mero-tee-v2.3.51node_url (alias nodeUrl) and release_tag (alias releaseTag) are both
accepted. When a URL parameter is present the page verifies automatically on
load; otherwise fill the form and submit.
Paste-attestation mode
Section titled “Paste-attestation mode”When you already have an attestation JSON (for example the response body of a
KMS /attest call, captured out of band), you can verify it directly without
the verifier reaching the instance. POST /api/verify accepts an attestation
object instead of a URL:
curl -s -X POST https://<verifier-host>/api/verify \ -H 'content-type: application/json' \ -d '{ "attestation": { "quote_b64": "<base64 raw TDX quote>", "reportDataHex": "<hex of the 64-byte report_data>", "eventLog": [ /* dstack event-log entries */ ] } }'The function extracts the quote (top-level quote_b64 for a KMS attestation, or
data.quoteB64 for a merod node response), sends it to Intel Trust Authority,
and returns the appraisal — ita_token, ita_token_verified, and ita_claims.
Because you supplied the attestation rather than a live nonce challenge, the
freshness check only applies if reportDataHex is present; the authenticity and
measurement checks run either way.
Next steps
Section titled “Next steps”- Getting Started — build and run the KMS and verifier locally.
- Verification — what the four verifier checks establish and why.
- Release pipeline — how the assets you verify here are produced and signed.
- Runbooks — deploy procedures that begin with this verification step.
- Calimero Core: TEE Attestation.